Skip to content

Latest commit

 

History

History
659 lines (559 loc) · 9.11 KB

README.md

File metadata and controls

659 lines (559 loc) · 9.11 KB

Stylus BEM mixins

stylus BEM syntactic sugar

Installation

npm install stylus-bem-mixins

Javascript API

var stylus = require('stylus')
var stylusBemMixins = require('stylus-bem-mixins')

var str = `
  @import 'node_modules/stylus-bem-mixins/index.styl'

  +b(button) {
    content: 'button';
    
    +e(icon) {
      content: 'icon';
      
      +m(small) {
        content: 'small';
      }
    }
  }
`

stylus(str)
  .use(stylusBemMixins())
  .render(function(err, css) {
    if (err) throw err
    console.log(css)
  })

Options:

You can custom separator

var option = {
  namespace: 'my', // default ''
  elementSeparator: '__', // default '__'
  modifierSeparator: '--', // default '--'
  statePrefix: 'is-' // default 'is-'
}
stylusBemMixins(option)

Using with Webpack

Use only the default settings, quick use

// in your stylus file
@import '~stylus-bem-mixins/index.styl'

Custom separator in webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.styl$/,
        use: [
          {
            loader: 'style-loader' // creates style nodes from JS strings
          },
          {
            loader: 'css-loader' // translates CSS into CommonJS
          },
          {
            loader: 'stylus-loader', // compiles Stylus to CSS
            options: {
              stylusOptions: {
                use: [
                  require('stylus-bem-mixins')({
                    namespace: 'my'
                  })
                ],
                import: ['stylus-bem-mixins']
              }
            }
          }
        ]
      }
    ]
  }
}

In Vue CLI

module.exports = {
  css: {
    loaderOptions: {
      stylus: {
        use: [
          require('stylus-bem-mixins')({
            namespace: 'my'
          })
        ],
        import: ['stylus-bem-mixins']
      }
    }
  }
}

Using with Gulp

// ...
const { series, src, dest } = require('gulp')
const stylus = require('gulp-stylus')
const stylusBemMixins = require('stylus-bem-mixins')({
  namespace: 'my'
})

function compileFile() {
  return src('./test.styl')
    .pipe(stylus({ use: stylusBemMixins }))
    .pipe(dest('./'))
}
series(compileFile)
// ...

Examples

Namespace is "my", other settings are default

Block

+b(form) {
  background: #ddd;
}

Compiles to:

.my-form {
  background: #ddd;
}

Element

+b(form) {
  background: #ddd;

  +e(input) {
    width: 200px;
  }

  +m(danger) {
    border: 1px solid #f00;

    +e(icon) {
      color: #f00;
    }
  }

  +when(loading) {
    color: #666;

    +e(input) {
      border-color: #ccc;
    }
  }
}

Compiles to:

.my-form {
  background: #ddd;
}
.my-form__input {
  width: 200px;
}
.my-form--danger {
  border: 1px solid #f00;
}
.my-form--danger .my-form__icon {
  color: #f00;
}
.my-form.is-loading {
  color: #666;
}
.my-form.is-loading .my-form__input {
  border-color: #ccc;
}

Modifier

+b(form) {
  background: #ddd;

  +m(danger) {
    border: 1px solid #f00;
  }

  +e(button) {
    border-radius: 4px;

    +m(small) {
      width: 150px;
    }
  }

  +when(disabled) {
    color: #999;

    +e(select) {
      border-color: #666;

      +m(small) {
        font-size: 12px;
      }
    }
  }
}

Compiles to:

.my-form {
  background: #ddd;
}
.my-form--danger {
  border: 1px solid #f00;
}
.my-form__button {
  border-radius: 4px;
}
.my-form__button--small {
  width: 150px;
}
.my-form.is-disabled {
  color: #999;
}
.my-form.is-disabled .my-form__select {
  border-color: #666;
}
.my-form.is-disabled .my-form__select--small {
  font-size: 12px;
}

State

This is optional prefix, you will use it in some cases, such as getting dom elements.

+b(form) {
  background: #ddd;

  +when(loading) {
    color: #666;
  }

  +e(button) {
    border-radius: 4px;

    +when(disabled) {
      color: #666;
    }
  }

  +m(danger) {
    border: 1px solid #f00;

    +e(input) {
      border-color: #f0a;

      +when(disabled) {
        color: #999;
      }
    }
  }
}

Compiles to:

.my-form {
  background: #ddd;
}
.my-form.is-loading {
  color: #666;
}
.my-form__button {
  border-radius: 4px;
}
.my-form__button.is-disabled {
  color: #666;
}
.my-form--danger {
  border: 1px solid #f00;
}
.my-form--danger .my-form__input {
  border-color: #f0a;
}
.my-form--danger .my-form__input.is-disabled {
  color: #999;
}

Same selector

Elements and Modifier can write multiple same selectors

+b(form) {
  background: #ddd;

  +e(input, button) {
    width: 200px;
  }

  +m(danger, success) {
    font-weight: bold;
  }
}

Compiles to:

.my-form {
  background: #ddd;
}
.my-form__input,
.my-form__button {
  width: 200px;
}
.my-form--danger,
.my-form--success {
  font-weight: bold;
}

Modifiercan nest in elements :

+b(form) {
  background: #ddd;

  +e(input, button) {
    width: 200px;

    +m(danger, success) {
      font-weight: bold;
    }
  }
}

Compiles to:

.my-form {
  background: #ddd;
}
.my-form__input,
.my-form__button {
  width: 200px;
}
.my-form__input--danger,
.my-form__button--danger,
.my-form__input--success,
.my-form__button--success {
  font-weight: bold;
}

Elements can nest in modifier:

+b(form) {
  background: #ddd;

  +m(danger, success) {
    font-weight: bold;

    +e(input, button) {
      width: 200px;
    }
  }
}

Compiles to:

.my-form {
  background: #ddd;
}
.my-form--danger,
.my-form--success {
  font-weight: bold;
}
.my-form--danger .my-form__input,
.my-form--success .my-form__input,
.my-form--danger .my-form__button,
.my-form--success .my-form__button {
  width: 200px;
}

Nesting rules

  1. "b" block mixins should be the outermost layer
  2. Cannot nest itself
  3. this is all nesting cases
    • B > E
    • B > E > M
    • B > E > when
    • B > M
    • B > M > E
    • B > M > E > when
    • B > when
    • B > when > E
    • B > when > E > M

Examples:

/*---------------------- B > E ----------------------*/
/*
+b(form) {
  background: #ddd;

  +e(input) {
    width: 200px;
  }
}
*/
.my-form {
  background: #ddd;
}
.my-form__input {
  width: 200px;
}
/*---------------------- B > E > M ----------------------*/
/*
+b(form) {
  background: #ddd;

  +e(button) {
    border-radius: 4px;

    +m(small) {
      width: 150px;
    }
  }
}
*/
.my-form {
  background: #ddd;
}
.my-form__button {
  border-radius: 4px;
}
.my-form__button--small {
  width: 150px;
}
/*---------------------- B > E > when ----------------------*/
/*
+b(form) {
  background: #ddd;

  +e(button) {
    border-radius: 4px;

    +when(disabled) {
      color: #666;
    }
  }
}
*/
.my-form {
  background: #ddd;
}
.my-form__button {
  border-radius: 4px;
}
.my-form__button.is-disabled {
  color: #666;
}
/*---------------------- B > M ----------------------*/
/*
+b(form) {
  background: #ddd;

  +m(danger) {
    border: 1px solid #f00;
  }
}
*/
.my-form {
  background: #ddd;
}
.my-form--danger {
  border: 1px solid #f00;
}
/*---------------------- B > M > E ----------------------*/
/*
+b(form) {
  background: #ddd;

  +m(danger) {
    border: 1px solid #f00;

    +e(icon) {
      color: #f00;
    }
  }
}
*/
.my-form {
  background: #ddd;
}
.my-form--danger {
  border: 1px solid #f00;
}
.my-form--danger .my-form__icon {
  color: #f00;
}
/*---------------------- B > M > E > when ----------------------*/
/*
+b(form) {
  background: #ddd;

  +m(danger) {
    border: 1px solid #f00;

    +e(input) {
      border-color: #f0a;

      +when(disabled) {
        color: #999;
      }
    }
  }
}
*/
.my-form {
  background: #ddd;
}
.my-form--danger {
  border: 1px solid #f00;
}
.my-form--danger .my-form__input {
  border-color: #f0a;
}
.my-form--danger .my-form__input.is-disabled {
  color: #999;
}
/*---------------------- B > when ----------------------*/
/*
+b(form) {
  background: #ddd;

  +when(loading) {
    color: #666;
  }
}
*/
.my-form {
  background: #ddd;
}
.my-form.is-loading {
  color: #666;
}
/*---------------------- B > when > E ----------------------*/
/*
+b(form) {
  background: #ddd;

  +when(loading) {
    color: #666;

    +e(input) {
      border-color: #ccc;
    }
  }
}
*/
.my-form {
  background: #ddd;
}
.my-form.is-loading {
  color: #666;
}
.my-form.is-loading .my-form__input {
  border-color: #ccc;
}
/*---------------------- B > when > E > M ----------------------*/
/*
+b(form) {
  background: #ddd

  +when(disabled) {
    color: #999;

    +e(select) {
      border-color: #666;

      +m(small) {
        font-size: 12px;
      }
    }
  }
}
*/
.my-form {
  background: #ddd;
}
.my-form.is-disabled {
  color: #999;
}
.my-form.is-disabled .my-form__select {
  border-color: #666;
}
.my-form.is-disabled .my-form__select--small {
  font-size: 12px;
}