Build material design interfaces in record time... without stress for devs... πŸΊπŸ’›

  • By beercss
  • Last update: Dec 24, 2022
  • Comments: 15

Beercss logo

License Downloads Size Version Pull Request Issues


Build material design interfaces in record time...

...without stress for devs 🍺 πŸ’›



  • It's based on latest material design patterns.
  • It's themeable.
  • It has zero dependencies.
  • It does a lot of combinations.
  • It's easy to work with Vue, React, Angular, Svelte and others.
  • It has about 10kb.
  • It has the most simple html output around.
  • It does not need tons of documentation to explain it.
  • It's fast to learn, read and write code.
  • It's like pure malt beer, only native and standard code.
  • No tricks, no build steps and no abstraction layers to try reduce your final code.
  • It's well designed and we hope that you can do a lot with it.

Applying "the beer way" in css?

This project was guided by the "Germany Beer Purity Law" or "Reinheitsgebot" created in 1516. This law states that beer should only be brewed with the following ingredients: water, barley malt and hops. Only 3 ingredients. Exciting, right? So we thinking about It and our 3 ingredients are: settings, elements and helpers. This sounds weird at first time, because It's not BEM, OOCSS, SMACSS, ITCSS, "Utility first" or any other approach. Our approach doesn't avoid some bad practices, but is lightweight, tasty and pure like a beer. Just try it and feel it! 😁

|  SETTINGS     |       // The settings affects all document
|               |    |
|  ELEMENTS     |    |  // The elements are the components, widgets or tags
|               |    |
|---------------|    |
|               |    |
|               |    |
|  HELPERS      |----|  // The common helpers makes the elements more scalable and customizable
|               |
|               |


// 1 setting to 1 document
<body class="light">...</body>
<body class="dark">...</body>

// 1 element to N helpers
<element class="helper helper">...</element>
<div class="element helper helper">...</div>

// nav elements before a main element
  <nav class="left m l">...</nav>
  <nav class="bottom s">...</nav>
  <main class="responsive">...</main>

<div id="app">
  <nav class="left m l">...</nav>
  <nav class="bottom s">...</nav>
  <main class="responsive">...</main>

// write css like this
.element.helper {...}
.element > .element {...}
.element > .helper {...}


// N elements to 1 tag
<div class="element element helper">...</div>

// element with dependencies
<div class="element">
  <div class="element-header">...</div>
  <div class="element-content">...</div>
  <div class="element-footer">...</div>

// nav elements after or inside a main element
  <main class="responsive">...</main>
  <nav class="left m l">...</nav>
  <nav class="bottom s">...</nav>

<div id="app">
  <main class="responsive">...</main>
  <nav class="left m l">...</nav>
  <nav class="bottom s">...</nav>

<main class="responsive">
  <nav class="left m l">...</nav>
  <nav class="bottom s">...</nav>

// write css like this
.element.element {...}
.element .element {...}
.element .helper {...}

Get started



<link href="[email protected]/dist/cdn/beer.min.css" rel="stylesheet" />
<script src="[email protected]/dist/cdn/beer.min.js" type="text/javascript"></script>
<script src="[email protected]/dist/cdn/material-dynamic-colors.min.js" type="text/javascript"></script>


You can get the latest release using NPM. This release contains source files as well as the compiled CSS and JavaScript files.

// installing
npm i beercss
npm i material-dynamic-colors
// importing
import "beercss";
import "material-dynamic-colors";


You can use this html to setup your project. See on Codepen.

    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta name="google" content="notranslate">
    <title>Hello world</title>
    <link href="[email protected]/dist/cdn/beer.min.css" rel="stylesheet">
    <script src="[email protected]/dist/cdn/beer.min.js" type="text/javascript"></script>
    <script src="[email protected]/dist/cdn/material-dynamic-colors.min.js" type="text/javascript"></script>
  <body class="light">
    <nav class="left m l">
      <img src="" class="circle large margin">
    <nav class="bottom s">
    <main class="responsive">
      <img src="" class="responsive">
      <h5>The beer is ready!</h5>

We recommend use the material-dynamic-colors only when your app needs to change theme at runtime.


Complete documentation and examples available at:

Contributing guide

Hi! We are really excited that you are interested in contributing to Beercss! Before submitting your contribution, please make sure to take a moment and read through the following guidelines:



Cheers to all people here 🍻

Stargazers repo roster for @beercss/beercss

Supporting us

Beercss is an MIT-licensed open source project with its ongoing development made possible entirely by the support of these awesome backers. If you'd like to join them, please consider:



  • 1


    convert from --size: 1px to --size: 16px - divide all existing rem values by 16

    This commit will not break anything inside of this library, but any user who used any rem values in their own project, will need to change the value to current rem value / 16.

  • 2

    GDPR Compliance and Google Fonts

    Thank you all for the good work you have done on this project.

    In January 2022, German courts made it so that unless web sites ask permission from their users for using Google Fonts before using it, they may be in violation of GDPR. Here is a blog post that talks about it:

    beercss seems to rely on Google hosted Roboto font and Material Symbols as found here:

    I would like to propose that instead of depending on Google hosted Roboto font and material symbols, we self host them within the project. By self hosting the font files, any project that uses beercss will not have to worry about building UIs for asking for user permission.

  • 3

    Introduce tiny chips and buttons

    Hello everyone and BeerCSS devs, I like this CSS framework! It's really useful, modern-looking, and simple πŸ˜„

    Can you guys add the tiny class to both chips and buttons? So it would look something like the picture below (I'm talking about the text that says "Gentoo Linux") label

    This could be especially useful to create label-looking elements. When writing paragraphs and we need to add labels, I feel chips and buttons, even with the small class, are just too big and mess up the text top & bottom alignment.

    Thanks in advance! Matteo

  • 4

    BeerCSS broken on older browsers

    Greetings, I would like to notify you all that BeerCSS does not render properly and is, in fact, broken, on older browsers, such as Firefox <= 72 (IIRC). When visiting, some buttons are inaccurately displayed, the icons in buttons either don't load at all or look huge (when they should appear next to the text inside the buttons).

    Going to post some screenshots later describing this issue further.

  • 5

    Firefox - Inputfields in details with value won't initialize right

    If you put an input field into an detail with a value before ui() is called, the borderline will be calculated wrong.

    Codepen Example:

    Steps to replicate:

    1. Put an input with label into a detail (not the summary).
    2. Give it a value to start, which is not empty.
    3. Then call the function ui().
    4. Open the detail and the border of the input was not calculated right and the borderline will go through the label text.

    My fix: Open all details, call ui() and then close them again. But it's not the most pretty fix.

    Maybe this fix or a better one could be included into the ui() function.

    Thanks in advance.

  • 6

    [Ask]How can i use progress bar as html without trigger ui()

    we don't need to call ui() anymore, but i'm wondering how to make items like progress bar move without trigger any script, maybe we can use something like

    <div class="progress left" id="cpu">{{ prec }}</div>
    export default {
      data() {
        return {
          prec: '40%'
  • 7

    Question: How to init the javascript?

    Hi, thanks for the library, but I am a little lost right now.

    I want to add it to my svelte app and adding it via "npm install" and "import beercss" works insofar as the css is applied.

    But the tabs for example dont work. How to switch the dark/light theme also eludes me.

    In the tab codepen ( I saw a call to ui(). Is that necessary to do so that the javascript is triggered?

    Thanks in advance for any help.

  • 8

    #86 Self host Google Fonts and Material Symbols

    With this PR, Roboto font files and Material Symbols woff2 files will be loaded using relative urls to the location of beer.min.css file instead of relying on the Google hosted version as default behavior. (I have created a new PR because the previous PR, now closed, got mangled up.)

  • 9

    Dropdowns using `details` and `summary` tags?

    Hi, currently dropdowns can be opened based on their focus status. I'm not sure if that's good for accessibility and it also means all of them are open when using the tab key to move inside the page. Recently expansions were added using details and summary html tags (great idea). What are your thoughts on using these tags as well for dropdowns instead of the focus trick? Is it better for accessibility? At least it fixes the automatic opening when focused…

    Cheers :beers: Laurent

  • 10

    Would Beer CSS want to merge with Materialize CSS to create one big community and framework?

    Beer CSS and Materialize CSS are both amazing frameworks that have similar design philosophy and their users and developers love. However, both have a small community and smaller communities generally cannot keep up with the updates of the world.

    It would be a shame if either of these frameworks would diminish forever because they dont have a big enough community to support them. I am thinking since both have similar design philosophy we can combine two small community frameworks to one bigger framework that has a way more developers combined working on it, is more feature rich, and more developers using it and creating issues to improve it. The framework may even be competing with bootstrap, foundation, and bulma in the future. I am wondering if Beer CSS would be willing to combine two small communities and frameworks to one big community for betterment of everyone involved?

  • 11

    JS: input is null when clicking on "radio" input

    Good morning everyone,

    in the file src/cdn/beer.js, this snippet here is problematic, for some unknown reason:

      const onClickLabel = (e) => {
        let input = query('input:not([type=file]):not([type=checkbox]):not([type=radio]), select, textarea', parent(e.currentTarget));

    When clicking a radio button, Firefox emits the following error in the console:

    Uncaught TypeError: e(...) is null
        d js/beer.min.js:1:888

    Here's a preview: bug

    Here's the code I wrote that handles the click event, and theme changing:

    /* This function sets light/dark theme */
    function update_light_settings() {
    	/* Get radio elements */
    	var theme_light = document.getElementById("theme_light");
    	var theme_dark  = document.getElementById("theme_dark");
    	/* Get current theme */
    	var theme = get_light();
    	/* Check radios accordingly */
    	if (theme == "dark")
    		theme_dark.checked = true;
    		theme_light.checked = true;
    	document.body.className = "is-" + theme;
    /* This function gets the current theme (light/dark) */
    function get_light() {
    	var l = document.body.className;
    	return (l == "is-dark" ? "dark" : "light");
    /* Update theme cookie */
    function update_cookie() {
    	document.cookie="theme=;path='/';SameSite=Lax;expires="+(new Date(0)).toUTCString();
    /* Get cookie */
    function getCookie(cname) {
    	let name = cname + "=";
    	let decodedCookie = decodeURIComponent(document.cookie);
    	let ca = decodedCookie.split(';');
    	for (let i = 0; i <ca.length; i++) {
    		let c = ca[i];
    		while (c.charAt(0) == ' ')
    			c = c.substring(1);
    		if (c.indexOf(name) == 0)
    			return c.substring(name.length, c.length);
    	return "";
    /* Get color accent (stored in cookie) */
    function get_accent() {
    	var accent = getCookie("accent");
    	return (accent != "" ? accent : undefined);
    /* Set appropriate theme (light/dark) */
    function toggle_light(callback) {
    	/* Get current theme from body class (<body class="is-...") */
    	var l = document.body.className;
    	document.body.className = "is-dark" == l ? "is-light" : "is-dark";
    	l = document.body.className;
    	/* Update theme cookie */
    	/* Get current color accent */
    	var accent = get_accent();
    	/* If accent is not undefined, aka it is set, set theme with accent */
    	if (accent != undefined)
    		ui("theme", { from: get_accent(), mode: get_light() });
    	/* If set, call callback */
    	if (callback != undefined)

    HTML (just the inputs):

    <input type="radio" name="theme" id="theme_light" onclick="toggle_light(update_light_settings)">

    Maybe (and I hope) it's just this code that's problematic. The "ui('theme')" and "material-dynamic-colors" functionality isn't well documented, in fact I had to look at several pages to understand how to apply a theme from a color, and Promise handling wasn't written in either one of them.

  • 12

    BeerCSS with NextJs

    Screenshot 2022-12-29 at 18-41-24 Screenshot

    How I get way with this?

    // Under _app.tsx
    import "beercss/src/cdn/beer.css";
    import "beercss/src/cdn/beer.ts";
    import "material-dynamic-colors";

    What I get in response? Yet another error!

    Screenshot from 2022-12-29 18-46-20

    So I rollback and try this:

    // Under _document.tsx
    export default function Document() {
      return (
            <link href="[email protected]/dist/cdn/beer.min.css" rel="stylesheet"/>
            {/* eslint-disable-next-line @next/next/no-sync-scripts */}
            <script src="[email protected]/dist/cdn/beer.min.js" type="text/javascript"/>
            {/* eslint-disable-next-line @next/next/no-sync-scripts */}
              src="[email protected]/dist/cdn/material-dynamic-colors.min.js"

    And someone it loads:

    Screenshot 2022-12-29 at 18-57-59 Screenshot

  • 13

    Standard navigation drawer

    Is it possible to use Navigation Drawer without being a modal?

    Standard drawers can be permanently visible (best for frequently switching destinations) or opened and closed by tapping a menu icon (best for focusing more on screen content).


  • 14

    Needs more examples

    As it's noted in the docs

    Build material design interfaces in record time... ...without stress for devs

    Unfortunately, I wasted a lot of time and could not make a simple dashboard layout like a this or this or at least this one

    I'm not front-end guy and I've found that using this framework is too hard for me. All existing templates like a Gmail, Netflix, Uber or Youtube look great but are useless. :-(

    Nevertheless, it looks pretty good. Maybe next time I'll use it in another project.

    Cheers! :)

  • 15

    Primary / secondary tabs

    I loved how v2.3.0 updated tabs from material design 3 guidelines. However, I had to add a few custom CSS rules to get closer to the MD3 specs and get primary and secondary tabs. My custom CSS is here:

    Do you think primary-tabs and secondary-tabs classes (or something like that) could be added to beercss to stick to the MD3 guidelines?