CSS: Styling a Component

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

Our main focus in this tutorial will be to build a rich product listing page inside of products.vue. To get that started, I'm going to replace the h1 with some new markup - you can copy this from the code block on this page.

<template>
<div class="container-fluid">
<div class="row">
... lines 4 - 53
</div>
</div>
</template>
... lines 57 - 68

Notice that there is nothing special yet. We're not rendering any variables: this is 100% static HTML. If you refresh the page, ok! We have a sidebar on the left, and an area on the right where we will eventually list some products. Good start!

Global CSS and Vue Components

And, though it's not pretty, it does already have some styling. If you look back at the HTML I just pasted, the basic styling is thanks to some Bootstrap classes that are on the elements. This works because, in the assets/scss/app.scss file, we're importing Bootstrap and I've decided to include the built app.css file on every page. So, naturally, if we use any Bootstrap classes in Vue, those elements get styled.

Custom Component style Section

But I also want to add some extra styling that's specific to the sidebar. The question is: where should that CSS live? We could, of course, add some classes to app.scss and use those inside our Vue component.

But Vue gives us a better option: because we want to style an element that's created in this component, Vue allows us to also put the styles in the component.

First, inside the aside element, give this <div> a new class called sidebar.

<template>
<div class="container-fluid">
<div class="row">
<aside class="col-xs-12 col-3">
<div class="sidebar p-3 mb-5">
... lines 6 - 29
</div>
</aside>
... lines 32 - 53
</div>
</div>
</template>
... lines 57 - 76

Next, at the bottom - though it doesn't matter where - there is third special section that any .vue file can have: you can have a <template> tag, a <script> tag and also a <style> tag. Inside, we're writing CSS: add .sidebar and let's give it a border, a box-shadow and a border-radius.

... lines 1 - 68
<style>
.sidebar {
border: 1px solid #efefee;
box-shadow: 0px 0px 7px 4px #efefee;
border-radius: 5px;
}
</style>

Styling done! Remember: we're still running yarn watch in the background, so Webpack is constantly re-dumping the built JavaScript and CSS files as we're working. Thanks to that, without doing anything else, we can refresh and... the sidebar is styled!

This works thanks to some Vue and Webpack teamwork. When Webpack sees the style tag, it grabs that CSS and puts it into the entry file's CSS file, so products.css.

View the page source: here's the link tag to /build/products.css. Whenever we add any styles to any component that this entry uses, Webpack will find those and put them in here. Like a lot of things with Webpack, it's not something you really need to think about: it just works.

Using Sass Styles

So this is awesome... but I do like using Sass. If you look at webpack.config.js, down here... yep! I've already added Sass support to Encore with .enableSassLoader().

Open up assets/scss/components/light-component.scss. This is a Sass mixin that holds the exact CSS I just added manually. If we could use Sass code inside the style tag, we could import this and save ourselves some duplication!

And that's totally possible: just add lang="scss".

... lines 1 - 68
<style lang="scss">
... lines 70 - 74
</style>

Now that we're writing Sass we can @import '../../scss/components/light-component' and inside .sidebar, @include light-component;.

... lines 1 - 68
<style lang="scss">
@import '../../scss/components/light-component';
.sidebar {
@include light-component;
}
</style>

Let's try it! Back over on your browser, refresh and... we have Sass!

To finish off the styling, I'll use Sass's nesting syntax to add a hover state on the links. Now after we refresh... got it!

... lines 1 - 71
.sidebar {
... lines 73 - 74
ul {
li a:hover {
background: $blue-component-link-hover;
}
}
}
... lines 81 - 82

Being able to put your styles right inside the component is one of my favorite features of Vue. And in a bit, we're going to do something even fancier with modular CSS.

Next, let's add some dynamic data back to our app and play with one of the coolest things in Vue: the developer tools.

Leave a comment!

  • 2020-07-09 Jakob B.

    Hey!

    I think one package was missing, I deleted node_modules and ran yarn install again :) It was a little weird, but now it works perfectly😀

  • 2020-07-08 weaverryan

    Hey @Jakob!

    Nice work! What was the final solution?

    Cheers!

  • 2020-07-07 Jakob B.

    I fixed it - Thank you very much for your answer :)

  • 2020-07-06 Jakob B.

    I am one step further: The .css is packed into the js directory, but it is not included on the page

  • 2020-07-06 Jakob B.

    Hey, thank you for your answer!

    ├─ vue-hot-reload-api@2.3.4
    ├─ vue-loader@15.9.3
    ├─ vue-style-loader@4.1.2
    ├─ vue-template-compiler@2.6.11
    ├─ vue-template-es2015-compiler@1.9.1
    ├─ vue@2.6.11

    I've just a style tag in the end of the template🙂

  • 2020-07-06 weaverryan

    Hey @Jakob!

    Hmm. Can you post your Vue file for us? I know you're doing everything one-to-one, but maybe there is something tiny that's wrong - that's the hardest stuff to find :). Also, what version of vue, vue-loader, vue-style-loader and vue-template-compiler do you have? You can find this by running yarn list --depth=0.

    Oh, and two more things - if you view source on the page, do you see a link tag for products.css? I want to make sure that is being included on the page (it is if you started with our code), And finally, when you run yarn watch what files does it say it is rendering? Do you see a products.css there?

    Cheers!

  • 2020-07-05 Jakob B.

    Hey! It does not work for me. If I write simple css at the end of my vue-file, it will not include anything. It is simply ignored and does not work at all. Any ideas? I've done everything one-to-one...

  • 2020-05-29 Alberto

    Wow, thanks!

  • 2020-05-29 Vladimir Sadicov

    Hey Alberto

    We are sorry about that, we have a little internal process where we add "code blocks" to the page - so they are not available immediately when chapter is released. We understand that it's a bit odd because Ryan said "copy the HTML from this page!"... but there is no HTML...yet
    Anyways code blocks will be able soon!

    Thanks for your attention to the details and watching new chapter as soon as it was released we really appreciate it!

    Cheers!

  • 2020-05-29 kraddle

    hi Alberto
    Here the code :
    https://github.com/SymfonyC...

  • 2020-05-29 Alberto

    Hey friends! We miss the code block in every video. It’s important to copy and paste in our code. The final code inside the dos loas its diferent than the current in each video. For example: all the css and html in this video. I hope yo can put them in every video like always.
    Thanks