Simple utility for creating declarative classnames in JSX for bulma.css using JavaScript objects
Writing long classnames for the Bulma.css stylesheet inline makes your code ugly and is hard to read at a glance, for example:
<h1 className="has-text-primary is-size-1-desktop is-size-2-tablet is-size-3-touch is-size-4-mobile has-text-left-mobile has-text-centered-desktop">Hello, world!</h1>
This problem gets even worse when you start to nest components and have a giant mess of spaghetti, for example:
<h1 className="has-text-primary is-size-1-desktop is-size-2-tablet is-size-3-touch is-size-4-mobile has-text-left-mobile has-text-centered-desktop">
Hello,
<a href="/world" className="has-text-secondary is-capitalized has-text-weight-bold">
world!
</a>
</h1>
Ugh!
The bulma-classnames
utility package helps you write these classnames using a simple javascript object in a more readable way. Here's the example from above rewritten in JSX and bulma-classnames
:
let styles = bulma({
textColor: 'primary',
textSize: ['1-desktop', '2-tablet', '3-touch', '4-mobile'],
textAlign: ['left-mobile', 'centered-desktop']
});
<h1 className={styles}>
Hello, world!
</h1>
And rewritten again inline if you prefer to do things that way:
<h1 className={
bulma({
textColor: 'primary',
textSize: ['1-desktop', '2-tablet', '3-touch', '4-mobile'],
textAlign: ['left-mobile', 'centered-desktop']
})
}>
Hello, world!
</h1>
So much better, right?!
What this package is not:
- A stylesheet. This package will only take in a declarative JavaScript object and return a formatted string for you to use as a classname in your code. You'll still need to install the Bulma.css stylesheet.
- Something that you'll use in a
<script>
tag in the browser. This package is designed to be used in a JSX environment, such as React.js, Preact.js or Inferno.
- The problem
- This solution
- Table of Contents
- Installation
- Usage
- API
- Learning Material
- FAQ
- Guiding Principles
- Roadmap
- Contributors
- Issues
- Feature Requests
- Questions
- Contributing
- Changelog
- LICENSE
This module is distributed via npm which is bundled with node and
should be installed as one of your project's dependencies
:
npm install bulma-classnames
Or via the yarn package manager:
yarn add bulma-classnames
Simply import bulma
into your file and use the function anywhere that you need to create a bulma classname string. The bulma
function accepts a JavaScript object with as many of the accepted key:value pairs shown in the API and returns a single, formatted string with all of the classnames.
import bulma from 'bulma-classnames'
// this will create the following string
// 'has-text-primary has-text-left is-size-1-mobile is-size-2-tablet is-size-3-mobile'
let styles = bulma({
textColor: 'primary',
textAlign: 'left',
textSize: ['1-desktop', '2-tablet', '3-mobile']
});
let MyComponent = (
<h1 className={styles}>
Hello, world!
</h1>
)
/*
*
* And this is what will be rendered
* let MyComponent = (
* <h1 className="has-text-primary has-text-left is-size-1-mobile is-size-2-tablet is-size-3-mobile">
* Hello, world!
* </h1>
* )
*
*/
You can also use the function inline if you prefer:
import bulma from 'bulma-classnames'
let MyComponent = (
<h1 className={
bulma({
textColor: 'primary',
textAlign: 'left',
textSize: ['1-desktop', '2-tablet', '3-mobile']
})
}>
Hello, world!
</h1>
)
/*
*
* And this is what will be rendered
* let MyComponent = (
* <h1 className="has-text-primary has-text-left is-size-1-mobile is-size-2-tablet is-size-3-mobile">
* Hello, world!
* </h1>
* )
*
*/
You can pass either a single string value:
let styles = bulma({
textColor: 'primary',
textAlign: 'left'
})
// 'has-text-primary has-text-left'
Or an array of values, which is extremely helpful for repetetive helpers with different values, like 'mobile,' 'tablet,' 'desktop,' etc. bulma
will format each array value with the correct prefix and combine them all into the same classname string.
let styles = bulma({
textSize: ['1-desktop', '2-tablet'],
textAlign: ['left-mobile', 'right-tablet', 'centered-desktop']
})
// 'is-size-1-desktop is-size-2-tablet has-text-left-mobile has-text-right-tablet has-text-centered-desktop'
And here's how you can change the name of the function during your import for a shorter syntax:
import bulma as bc from 'bulma-classnames'
let MyComponent = (
<h1 className={
bc({
textColor: 'primary',
textAlign: 'left',
textSize: ['1-desktop', '2-tablet', '3-mobile']
})
}>
Hello, world!
</h1>
)
/*
*
* And this is what will be rendered
* let MyComponent = (
* <h1 className="has-text-primary has-text-left is-size-1-mobile is-size-2-tablet is-size-3-mobile">
* Hello, world!
* </h1>
* )
*
*/
Although it's preferred to use the most specific key instad of is
or has
, you can always use these helpers as an escape hatch or for simple helpers like is-marginless
.
let styles = bulma({
is: ['marginless'],
textAlign: ['addons', 'addons-right']
})
// 'is-marginless has-addons has-addons-right'
And here's an example of a bad way to use the is
and has
helper, since it's harder to read at a glance and is less declarative:
let styles = bulma({
is: 'capitalized',
has: ['text-right-mobile', 'text-left-desktop']
})
// 'is-capitalized has-text-right-mobile has-text-left-desktop'
And the better way to accomplish the same example above, but more declaratively:
let styles = bulma({
textTransform: 'capitalized',
textAlign: ['right-mobile', 'left-desktop']
})
// 'is-capitalized has-text-right-mobile has-text-left-desktop'
raw
is a simple way to add extra classnames without formatting them. Any string that you add in raw
will be added to the end of the classname string.
let styles = bulma({
color: 'primary',
raw: 'extra-classname another-classname'
})
// 'is-primary extra-classname another-classname'
Here's a list of all the accepted keys and their types.
string
- adds "is-background-" to the front of the string
bulma({
backgroundColor: 'primary'
})
// => 'is-background-primary'
string
- adds "is-" to the front of the string
bulma({
color: 'primary'
})
// => 'is-primary
string | string[]
- adds "is-" to the front of each string and "column" to the end
bulma({
column: '10-mobile'
})
// => 'is-10-mobile column'
bulma({
column: [ '10-mobile', '11-desktop', '12-widescreen']
})
// => 'is-10-mobile is-11-desktop is-12-widescreen column'
string | string[]
- adds "is-offset-" to the front of each string
bulma({
offset: '10-mobile'
})
// => 'is-offset-10-mobile'
bulma({
offset: [ '10-mobile', '11-desktop', '12-widescreen']
})
// => 'is-offset-10-mobile is-offset-11-desktop is-offset-12-widescreen'
string | string[]
- adds "is-flex" to the front of each string
bulma({
flex: 'mobile'
})
// => 'is-flex-mobile'
bulma({
flex: [ 'mobile', 'desktop', 'widescreen']
})
// => 'is-flex-mobile is-flex-desktop is-flex-widescreen'
string | string[]
- adds "is-inline-flex" to the front of each string
bulma({
inlineFlex: 'mobile'
})
// => 'is-inline-flex-mobile'
bulma({
inlineFlex: [ 'mobile', 'desktop', 'widescreen']
})
// => 'is-inline-flex-mobile is-inline-flex-desktop is-inline-flex-widescreen'
string | string[]
- adds "is-block" to the front of each string
bulma({
block: 'mobile'
})
// => 'is-block-mobile'
bulma({
block: [ 'mobile', 'desktop', 'widescreen']
})
// => 'is-block-mobile is-block-desktop is-block-widescreen'
string | string[]
- adds "is-inline-block" to the front of each string
bulma({
inlineBlock: 'mobile'
})
// => 'is-inline-block-mobile'
bulma({
inlineBlock: [ 'mobile', 'desktop', 'widescreen']
})
// => 'is-inline-block-mobile is-inline-block-desktop is-inline-block-widescreen'
string | string[]
- adds "is-inline" to the front of each string
bulma({
inline: 'mobile'
})
// => 'is-inline-mobile'
bulma({
inline: [ 'mobile', 'desktop', 'widescreen']
})
// => 'is-inline-mobile is-inline-desktop is-inline-widescreen'
string
- adds "has-text-color" to the front of the string
bulma({
textColor: 'primary'
})
// => 'has-text-color-primary
string | string[]
- adds "is-size-" to the front of the string
bulma({
textSize: '6'
})
// => 'is-size-6'
bulma({
textSize: ['5-mobile', '6-desktop', '7-widescreen']
})
// => 'is-size-5-mobile is-size-6-desktop is-size-7-widescreen'
string
- adds "has-text-weight" to the front of the string
bulma({
textWeight: 'bold'
})
// => 'has-text-weight-bold'
string | string[]
- adds "is-" to the front of the string
bulma({
textTransformation: 'capitalized'
})
// => 'is-capitalized'
bulma({
textTransformation: ['capitalized', 'italic']
})
// => 'is-capitalized is-italic'
` string | string[]``` - adds "has-text-" to the front of the string
bulma({
textAlign: 'left'
})
// => 'has-text-left'
bulma({
textAlign: ['left-mobile', 'right-desktop', 'center-widescreen']
})
// => 'has-text-left-mobile has-text-right-desktop has-text-center-widescreen'
string | string[]
- adds "is-" to the front of each string. Designed as an escape hatch, or for misc. helpers like is-marginless
bulma({
is: 'marginless'
})
// => 'is-marginless'
bulma({
is: ['marginless', 'pulled-left']
})
// => 'is-marginless is-pulled-left'
string | string[]
- adds "has-" to the front of each string. Designed as an escape hatch, or for misc. helpers like has-addons
bulma({
has: 'addons'
})
// => 'has-text-weight-bold'
bulma({
has: ['addons', 'addons-right']
})
// => 'has-addons has-addons-right'
string
- outputs the exact same string that is passed, no formatting is added. Useful to pass extra classnames that either don't start with is
or has
o aren't related to Bulma in the same object
bulma({
raw: 'column'
})
// => 'column'
Feel free to contribute more!
Are there Flow and TypeScript types available?
Not yet, but I'm working on them and expect to have them finished soon. You can see my progress and contribute if you like!
What is Bulma.css?
Bulma.css is a beautiful stylesheet with helpers and components already pre-designed for you, like Bootstrap or Foundation. It uses classnames to reference the styles and is great for developers new to styling websites, or anyone that wants to use a battle-tested stylesheet to get going fast on a project. I used it heavily in my other project Sushi Commerce and it drove me to create this package to save hours of time and make my code much prettier to look at and reason about.
What if I hate CSS-in-JS?
Then this might still be great for you, because you're still doing the same thing as standard CSS - add classnames to an HTML object. But you're doing it more declaratively and modern. t still might feel weird putting your styles in an object at first though, and that's ok.
Long classname strings suck to write and suck to look at - JavaScript objects are much easier.
I think it's much more fun to write a declarative object in a small function to write my styles, while using the amazing Bulma.css stylesheet.
This package is a single function that formats the object with a class that has several switch statements and reducer functions.
- Flow and TypeScript typings
Looking to contribute? Check out our roadmap and raise an issue on what you'd like to help with!
Please raise an issue for bugs, missing documentation, or unexpected behavior.
Please raise an issue to suggest new features. Vote on feature requests by adding a 👍. This helps maintainers prioritize what to work on.
Please raise an issue if you have any questions about how to use this package.
Contributions are welcome! If you'd like to help out, check the issues or create a new issue and let us know what you plan to work on. When you're ready to start, visit out instructions on how to contribute for more information.
View the changelog to see all updates, which will be automatically updated by commitizen
and semantic-release
.
MIT