Did you ever run into issues where you didn't know which of your stylings is overwriting some HTML elements style or would just interfere with another styling? Well, me too. Using CSS can be pretty overwhelming, especially with increasing complexity of your website or app. There are a lot of methodologies to help you out with that, such as BEM (Block Element Modifier), SMACSS (Scalable and Modular Architecture for CSS), OOC (Object Oriented CSS) and many more and all of them aim for the purpose of providing a suitable CSS architecture to support you during your development.
I like the idea of structured CSS. Your styles will be easier to read and understand. Especially, thanks to CSS pre-processors such as SASS or LESS, this even got better. Your styles get easier to write, read and maintain while simultaneously keeping your markup gets easy as well. Well, that sound good! But not every methodology might suit your needs or personal preferences. Depending on your favored methodology or even just your individual style, it might be possible that you run into previously mentioned issues.
Let's imagine you're going to build a pretty simple box layout through your whole website with a border and a padding of 10 pixels on each side. Your code could look like this.
So what happened here? We've just added a simple container with a given class name called box
and also added the styles for that class. But what happens if we now want to extend that box' style? Let's say we want it to have a padding of 20 pixels on the left and right side while leaving the upper and below ones at 0? Sounds simple. Let's give it a try.
You might have noticed that new class plr-20
which only adds a padding to the left
and right
side. You also might have noticed that our box still has those 10 pixels of a padding set on the other sides because they are defined within our box
class. "What's the deal?" you might ask. You could have just set those padding to 0 and overwrite the box
styles. Well, that's true. But imagine you're having a lot more global classes with similar styles - they might interfere with each other. So how could we solve that problem?
Single File Components and the <style> block
If you're familiar with Vue.js and already know about SFCs (Single File Components) you might have stumbled upon scoped styles already. If not, don't worry. We'll tackle that in a moment.
SFCs became pretty much standard within the Vue community and it's currently likely the best, if not the easiest way of how to build your components. Unlike other frameworks using a SFC you can separate your HTML markup as well as your JavaScript and CSS code into separate blocks within the same file. That said, the code in a Vue SFC is split into a <template>
, <script>
and a <style>
block. This not only helps you to maintain your code but also provides some serious structure. But enough of that. Let's get right to the point now and see what scoped styles are and how they help us.
Let's focus on the <style>
block for now. It's purpose is pretty clear. You can define any style you want within that block. Initially it just supports CSS, so you could simply copy all CSS from our previous example and put it in there. But it can get extended pretty easily to support pre-processors by just adding a lang
attribute such as <style lang="scss">
. Doing so you just get the possibility to use SCSS. But we still didn't get a solution for our problem with interfering styles. Well, that's where the scoped
attribute kicks in.
Scoped styles to the rescue!
Using <style scoped>
you just enable scoped styles. But what exactly does that mean? What's its benefit? Remember our previous example with the interfering box
class, that just added an unwanted padding? We could have fixed that by simply extending our plr-20
class but this could eventually interfere with some other class later on. The major benefit of the scoped style block is, that anything you define there will stick to that given component. That's ensured through a generated hash which gets added to any class name as well as and DOM element of that component. So that means, if we use an additional class to fix the padding issue, it would only work within that component. So we wouldn't affect any global styles. That's cool! But what about child components? Do the styles work for them as well? Good question! Short answer is - maybe. Regarding any child component, scoped styles only work for the childs root element. But what if you want the styles to work on the child any any other nester element as well? There's a solution for this too.
Passing scoped styles to child components
You can pass scoped styles down the DOM tree by using the deep selector. Depending on your used pre-processor you might use >>>
, /deep/
or ::v-deep
. You can find more on that at the Vue Loader docs.