Skip to content

tomhayes/BEMoji

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

9 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🎯 BEMoji

BEM, but every class name is an emoji.

BEMoji is a production-grade CSS framework that implements the BEM (Block–Element–Modifier) methodology using emoji as class names. It ships with a full design token system, 24 pre-built components, responsive utilities, and a complete build toolchain.

npm version License: MIT PRs Welcome

<!-- This is valid, production HTML -->
<article class="πŸƒ">
  <div class="πŸƒ__πŸ–ΌοΈ πŸƒ__πŸ–ΌοΈ--🌟">
    <img src="hero.jpg" alt="...">
  </div>
  <div class="πŸƒ__πŸ“">
    <h2 class="πŸƒ__πŸ” ">Card Title</h2>
  </div>
  <footer class="πŸƒ__🦢">
    <button class="πŸ”˜ πŸ”˜--🌟">Primary</button>
    <button class="πŸ”˜ πŸ”˜--πŸ‘»">Disabled</button>
  </footer>
</article>

Why?

BEMoji Tailwind BEM CSS Modules
Zero runtime JS βœ“ βœ“ βœ“ βœ“
Automatic obfuscation βœ“ βœ— βœ— build-time
Semantic naming βœ“ βœ— βœ“ βœ“
Design token system βœ“ βœ“ βœ— βœ—
Pre-built components βœ“ βœ— βœ— βœ—
Colleague confusion Maximum Moderate Minimal Minimal

Genuine reasons to use BEMoji:

  1. Free obfuscation β€” Emoji class names are meaningless to scrapers and competitors without your config file. You get CSS-modules-style obfuscation without the build complexity.
  2. Enforced vocabulary β€” Every UI concept maps to one canonical emoji. The config file is your design system contract.
  3. Faster to type β€” πŸƒ is two keystrokes with an emoji picker. .card__image--featured is 24.
  4. It actually works β€” Modern browsers handle emoji in CSS selectors natively. The compiler handles escaped unicode fallbacks for older environments.

Installation

npm install bemoji
# or
yarn add bemoji
# or
pnpm add bemoji

Quick start

npx bemoji init

This scaffolds a bemoji.config.js, imports the base CSS, and wires up PostCSS.


Core Concepts

Naming Anatomy

πŸƒ  __  πŸ–ΌοΈ  --  🌟
β”‚       β”‚       └─ Modifier  (state or variant)
β”‚       └───────── Element   (part of the block)
└───────────────── Block     (standalone component)

Delimiters are identical to BEM: __ for elements, -- for modifiers. The framework is machine-parseable even if it isn't human-readable.

Block

A standalone, reusable component. Carries no inherited context.

.πŸƒ  /* card  */
.🧭  /* navbar */
.πŸ“‹  /* form  */

Element

A part of a block. Always expressed as block__element. Cannot exist outside its block.

.πŸƒ__πŸ–ΌοΈ  /* card image  */
.πŸƒ__πŸ”   /* card title  */
.πŸƒ__πŸ“  /* card body   */

Modifier

A flag that changes appearance or behavior. Applied alongside the base class.

.πŸ”˜--🌟  /* button primary */
.πŸ”˜--πŸ”΄  /* button danger  */
.πŸ”˜--πŸ‘»  /* button disabled */

The Emoji Lexicon

BEMoji defines 143 reserved tokens. Here are the core ones:

Blocks (Components)

Emoji Name Aliases
πŸƒ card panel, tile
🧭 navbar nav, header
🦢 footer β€”
πŸ“‹ form β€”
πŸͺŸ modal dialog, overlay
πŸ”” alert notification
🏷️ badge tag, chip
πŸ’¬ tooltip popover
πŸ“Š table β€”
πŸ“‘ tabs β€”
🎠 carousel slider
🍞 breadcrumb β€”

Elements (Parts)

Emoji Name Aliases
πŸ–ΌοΈ image img, media
πŸ”  title heading
πŸ“ body content, text
🦢 footer actions
πŸ”˜ button btn, cta
πŸ“₯ input field, control
πŸ”— link anchor
🏷️ label β€”
🎭 icon β€”
πŸ“„ item row, entry

Modifiers (States)

Emoji Name Aliases
🌟 primary featured, hero
πŸ”΄ danger error, destructive
🟒 success ok, valid
🟑 warning caution
πŸ”΅ info β€”
πŸ‘» disabled ghost, muted
βœ… active selected
⏳ loading pending, busy
πŸ”’ locked readonly
πŸ’Ž premium pro
πŸ†• new fresh

Modifiers (Size)

Emoji Name
πŸ”¬ xs
🀏 sm
βš–οΈ md
πŸ‹οΈ lg
πŸ”οΈ xl
🌍 2xl

Design Tokens

BEMoji's token system uses emoji as CSS custom property names β€” the obfuscation extends all the way to your design tokens.

:root {
  /* Colors */
  --⬛: #0d0d0f;
  --⬜: #ffffff;
  --πŸ”΄: #dc2626;
  --🟒: #16a34a;
  --🟑: #d97706;
  --πŸ”΅: #2563eb;
  --🟣: #7c3aed;

  /* Spacing scale */
  --πŸ“-1: 0.25rem;  /* 4px  */
  --πŸ“-2: 0.5rem;   /* 8px  */
  --πŸ“-4: 1rem;     /* 16px */
  --πŸ“-6: 1.5rem;   /* 24px */
  --πŸ“-8: 2rem;     /* 32px */
  --πŸ“-12: 3rem;    /* 48px */
  --πŸ“-16: 4rem;    /* 64px */

  /* Typography */
  --✍️-xs:   0.75rem;
  --✍️-sm:   0.875rem;
  --✍️-base: 1rem;
  --✍️-lg:   1.125rem;
  --✍️-xl:   1.25rem;

  /* Shadows */
  --πŸŒ‘-sm: 0 1px 3px rgba(0,0,0,.12);
  --πŸŒ‘-md: 0 4px 12px rgba(0,0,0,.15);
  --πŸŒ‘-lg: 0 8px 24px rgba(0,0,0,.2);

  /* Border radius */
  --β­•-sm:   4px;
  --β­•-md:   8px;
  --β­•-lg:   16px;
  --β­•-full: 9999px;
}

Responsive System

Breakpoints use an emoji prefix separated by a zero-width joiner (U+200D):

Emoji Breakpoint Range
πŸ“± xs 0–639px (base, no prefix)
πŸ“Ÿ sm 640px+
πŸ“² md 768px+
πŸ’» lg 1024px+
πŸ–₯️ xl 1280px+
<!-- 1 col mobile, 2 col tablet, 3 col desktop -->
<div class="πŸ“πŸ’  πŸ“²πŸ“πŸ”² πŸ’»πŸ“πŸ”³">
  ...
</div>

Usage with PostCSS

Write readable BEM names in brackets in your source CSS:

.[card] {
  border-radius: var(--β­•-md);
  box-shadow: var(--πŸŒ‘-sm);
  background: var(--⬜);
}

.[card__image] {
  width: 100%;
  aspect-ratio: 16 / 9;
}

.[card__image--featured] {
  outline: 2px solid var(--🟑);
  outline-offset: -2px;
}

The PostCSS plugin compiles this to:

.πŸƒ { border-radius: var(--β­•-md); box-shadow: var(--πŸŒ‘-sm); background: var(--⬜); }
.πŸƒ__πŸ–ΌοΈ { width: 100%; aspect-ratio: 16 / 9; }
.πŸƒ__πŸ–ΌοΈ--🌟 { outline: 2px solid var(--🟑); outline-offset: -2px; }

Usage with React

import { bem } from 'bemoji/react';

const Card = ({ featured, loading, children }) => (
  <article className={bem('card')}>
    <div className={bem('card__image', { featured, loading })}>
      {children.image}
    </div>
    <div className={bem('card__body')}>
      {children.body}
    </div>
  </article>
);

// bem('card')                    β†’ 'πŸƒ'
// bem('card__image', { featured: true })  β†’ 'πŸƒ__πŸ–ΌοΈ πŸƒ__πŸ–ΌοΈ--🌟'
// bem('card__image', { loading: true })   β†’ 'πŸƒ__πŸ–ΌοΈ πŸƒ__πŸ–ΌοΈ--⏳'

Configuration

// bemoji.config.js
export default {
  version: '1.0',

  blocks: {
    card:       'πŸƒ',
    navbar:     '🧭',
    modal:      'πŸͺŸ',
    alert:      'πŸ””',
    form:       'πŸ“‹',
    table:      'πŸ“Š',
    badge:      '🏷️',
    tooltip:    'πŸ’¬',
    tabs:       'πŸ“‘',
    carousel:   '🎠',
    breadcrumb: '🍞',
    footer:     '🦢',
  },

  elements: {
    image:   'πŸ–ΌοΈ',
    title:   'πŸ” ',
    body:    'πŸ“',
    footer:  '🦢',
    button:  'πŸ”˜',
    input:   'πŸ“₯',
    link:    'πŸ”—',
    label:   '🏷️',
    icon:    '🎭',
    item:    'πŸ“„',
    divider: 'πŸ–‡οΈ',
  },

  modifiers: {
    primary:  '🌟',
    danger:   'πŸ”΄',
    success:  '🟒',
    warning:  '🟑',
    info:     'πŸ”΅',
    disabled: 'πŸ‘»',
    active:   'βœ…',
    loading:  '⏳',
    locked:   'πŸ”’',
    premium:  'πŸ’Ž',
    new:      'πŸ†•',
    dark:     'πŸ•ΆοΈ',
    xs:       'πŸ”¬',
    sm:       '🀏',
    md:       'βš–οΈ',
    lg:       'πŸ‹οΈ',
    xl:       'πŸ”οΈ',
  },

  breakpoints: {
    sm: { prefix: 'πŸ“Ÿ', minWidth: '640px'  },
    md: { prefix: 'πŸ“²', minWidth: '768px'  },
    lg: { prefix: 'πŸ’»', minWidth: '1024px' },
    xl: { prefix: 'πŸ–₯️', minWidth: '1280px' },
  },

  separator: {
    element:  '__',
    modifier: '--',
  },

  compiler: {
    escape:    'auto',   // 'raw' | 'unicode' | 'auto'
    sourceMap: true,
    purge:     true,
  },
};

CLI

npx bemoji init                    # Scaffold project
npx bemoji compile                 # Transform CSS files
npx bemoji audit                   # Check for unused tokens
npx bemoji decode "πŸƒ__πŸ–ΌοΈ--🌟"  # β†’ card__image--featured
npx bemoji encode "card__image--featured"  # β†’ πŸƒ__πŸ–ΌοΈ--🌟
npx bemoji export --fmt json       # Export token map as JSON
npx bemoji storybook               # Generate Storybook stories

Tooling Ecosystem

Package Description
bemoji Core framework + CSS
bemoji-postcss PostCSS plugin
vite-plugin-bemoji Vite integration
bemoji/react React bem() helper
eslint-plugin-bemoji ESLint rules
bemoji-cli CLI tools

VS Code extension β€” Search "BEMoji" in the Extensions marketplace for IntelliSense, hover tooltips, and autocomplete.


Browser Support

BEMoji targets the same browser support as Baseline 2023. Emoji class names work natively in all modern browsers. The compiler can output unicode-escaped fallbacks (.\01F0CF) for older Webkit environments via the escape: 'unicode' config option.


Contributing

PRs are welcome. See CONTRIBUTING.md for guidelines.

The most impactful contributions are:

  • New emoji token proposals (open an RFC issue first)
  • Framework adapter packages (Svelte, Vue, Angular)
  • The actual npm packages (this repo contains complete, functional implementations)

License

MIT Β© BEMoji Contributors


"It works. We're as surprised as you are."

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors