Scalable
Component
Styles
A well-designed system makes it easy to do the right things and annoying (but not impossible) to do the wrong things
The Pit of Success
https://blog.codinghorror.com/falling-into-the-pit-of-success/
Let's Pretend JS was CSS
Problems with CSS
-
Global Namespace
-
Implicit dependencies
-
Poor Isolation
-
Dead code / duplication
-
Non-deterministic resolution
CSS conventions and tools
- Naming Conventions
- Scoped Styles
- CSS Modules
CSS in JS
BEM
.Block
__element
--modifier
Naming Conventions
BEM
<template>
<div class="TheGreeting">
<h1 class="TheGreeting__headline">Hello world</h1>
<div class="TheGreeting__body">
<BaseButton text="Say Hello"/>
</div>
</div>
</template>
<style>
.TheGreeting {
border: 1px solid black;
}
.TheGreeting__headline {
color: blue;
}
</style>
components/TheGreeting.vue
BEM
<template>
<div class="TheGreeting">
<h1 class="TheGreeting__headline">Hello world</h1>
<BaseButton text="Say Hello"/>
</div>
</template>
<style>
.TheGreeting .BaseButton {
margin: 10px;
}
</style>
components/TheGreeting.vue
BEM
<template>
<div class="TheGreeting">
<h1 class="TheGreeting__headline">Hello world</h1>
<BaseButton class="TheGreeting__BaseButton" text="Say Hello"/>
</div>
</template>
components/TheGreeting.vue
class is a prop and it's invalid
<template functional>
<div class="BaseButton" :class="props.className">
<button class="BaseButton__button">{{ props.text }}</button>
</div>
</template>
<template>
<div class="TheGreeting">
<h1 class="TheGreeting__headline">Hello world</h1>
<BaseButton className="TheGreeting__BaseButton" text="Say Hello"/>
</div>
</template>
BEM
<template>
<div class="TheGreeting">
<h1 class="TheGreeting__headline">Hello world</h1>
<div class="TheGreeting__body">
<BaseButton text="Say Hello"/>
</div>
</div>
</template>
<style lang="stylus">
import '~styles/brand-presets.css';
.TheGreeting {
border: 1px solid black;
&__headline {
color: headline-color;
}
}
</style>
components/TheGreeting.vue
Scoped Styles
<div data-v-6b11abfc class="TheGreeting">
<h2 data-v-6b11abfc class="headline">Hello world</h2>
<div data-v-6b11abfc class="body">
<!-- ... -->
</div>
</div>
<template>
<div class="TheGreeting">
<h2 class="headline">Hello world</h2>
<div class="body">
<!-- ... -->
</div>
</div>
</template>
<style scoped>
// Styles here...
</style>
components/TheGreeting.vue
Markup result
Scoped Styles
<template>
<div class="TheGreeting">
<h2 class="headline">Hello world</h2>
<!-- ... -->
</div>
</template>
<style scoped>
.headline {
color: red;
}
</style>
components/TheGreeting.vue
.headline[data-v-6b11abfc] {
color: red;
}
output stylesheet
CSS-Modules
<template>
<div :class="$style.TheGreeting">
<h2 :class="$style.headline">Hello world</h2>
<!-- ... -->
</div>
</template>
<style module>
.headline {
color: red;
}
</style>
components/TheGreeting.vue
<div>
<h2 class="_components_TheGreeting__headline">
Hello world
</h2>
</div>
output markup
CSS-Modules
<template>
<div :class="$style.TheGreeting">
<h2 :class="$style.headline">Hello world</h2>
<!-- ... -->
</div>
</template>
<style module>
.headline {
background-color: black;
composes: headline-color from '../presets.css';
}
</style>
components/TheGreeting.vue
<div>
<h2 class="_components_TheGreeting__headline
_123_headline-color">
Hello world
</h2>
</div>
output markup
Resouces
deck
By Justin Bennett
deck
- 1,172