Using SASS in Vue Components with Laravel Mix

Part 11 of 48 in API Driven Development With Laravel and VueJS
Dan Pastori avatar
Dan Pastori October 23rd, 2017
⚡️ Updated content is available We learned a lot since we originally wrote this article. We now have this updated for Laravel 10, Vue 3/NuxtJS 3, and Capacitor 3.

On of the most powerful features of Vue Components or Web components for that matter is all of your CSS, HTML, and Javascript are in the same file. This makes managing all factors of the component extremely easy. If you are using SASS in your project and you want to carry in your variables for your Vue components, it can be a little tricky. It’s definitely useful though and can really help with managing your project.

Now in the tutorial about configuring Javascript and SASS for your single page application: https://serversideup.net/configuring-js-sass-single-page-app/, we built a directory structure for all of the assets of SASS. These are still useful! You can easily place your SASS for your Vue components in these directories if needed. We will still be using these directories as buckets to house our SASS as our app expands.

Step 1: Make Your Variables File

Right now, since we are using Foundation for some quick grid functionality, our most important file will be our _variables.scss file that we will include all of our SASS Variables for the app. Following the 7-1 pattern ( Sass Guidelines) we should add a file in the /assets/sass/abstracts directory named _variables.scss.

I added a few default colors (kind of coffee based since we are doing a coffee app) to the variables file. It should look like this:

$white: #FFFFFF;
$black: #111111;

$primary-color: #7F6D50;
$secondary-color: #FFBE54;
$highlight-color: #FFDBA0;
$dark-color: #7F5F2A;
$dull-color: #CCAF80;

We now have some colors to use in the components! If you want a cool tool for non-designers like myself, check out Adobe Color CC. Here’s the link I used to generate my coffee colors: Adobe Color CC

Step 2: Add Variables File To App.scss

We need to import our newly created variable file into our assets/sass/app.scss file so it will be compiled into our CSS when we build our application. To do that add this line to your app.scss file:

@import 'abstracts/variables';

Your file should look like this:

@charset "UTF-8";

/* ==========================================================================
    Builds our style structure
        https://sass-guidelin.es/#the-7-1-pattern
   ========================================================================== */
/**
 * Table of Contents:
 *
 *  1. Abstracts
 */
@import 'abstracts/variables';

@import "node_modules/foundation-sites/assets/foundation.scss";

Step 3: Add Alias To webpack.mix.js

Now this is what ties everything together to allow use to use Laravel Mix and SASS with our Vue components. What we essentially need to do is define an alias or variable that contains the path to our sass directory so we can include that SASS in our Vue components. 99% of the time we should just be including our variables file because we are defining all of the other styles in the Vue Component it self. I still keep all the directories for the 7-1 pattern for global styles, simple element styles like button components, custom grids if needed, etc. To add the alias add the following to your webpackConfig object in your webpack.mix.js:


resolve: {
    alias: {
        '@': path.resolve('resources/assets/sass')
    }
}

This solution was found here: tutorial How to use global Sass vars within Vue Single File Components · Issue #1023 · JeffreyWay/laravel-mix · GitHub. What we did is when we build our app, we resolve the @ as an alias for our resources, assets, sass directory. Our entire webpack.mix.js file should look like:

let mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel application. By default, we are compiling the Sass
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.js('resources/assets/js/app.js', 'public/js')
    .webpackConfig({
         module: {
             rules: [
                 {
                     test: /\.jsx?$/,
                     exclude: /node_modules(?!\/foundation-sites)|bower_components/,
                     use: [
                         {
                             loader: 'babel-loader',
                             options: Config.babel()
                         }
                     ]
                 }
             ]
         },
         resolve: {
            alias: {
              '@': path.resolve('resources/assets/sass')
            }
          }
     })
   .sass('resources/assets/sass/app.scss', 'public/css');

We added the other code to allow for a production build of foundation.

Step 4: Add Navigation Vue Component

Time to add our first Vue component to Roast and Brew! Now that we have SASS ready to compile into our Vue component, we should be ready to rock and roll with building what we need. First, add the file: resources/assets/js/components/global/Navigation.vue. We created a global directory as well. I like to structure the components in folders for grouping especially with parent/child combinations. Just makes things easier to find. In the Navigation.vue component, stub out the following code:

<style>

</style>
<template>
    <nav class="top-navigation">

    </nav>
</template>
<script>
    export default {

    }
</script>

This is just the base for the component. Next we have to tell Vue that we are using SCSS in our <style> tag instead of CSS. To do that add a property of lang=“scss" to the the <style> tag.

Next, we need to import our SCSS variables. Since we defined it to resolve @ as the root directory for the SCSS, we can add this as the first line in the style tag:

@import '~@/abstracts/_variables.scss';

Now we are importing our SCSS variables in our Navigation.vue component! It should look like this all stubbed out:

<style lang="scss">
    @import '~@/abstracts/_variables.scss';
</style>
<template>
    <nav class="top-navigation">

    </nav>
</template>
<script>
    export default {

    }
</script>

This component will be our navigation bar for our application. Notice we also used a <nav tag. I try to follow the HTML5 semantics whenever possible. If you haven’t done HTML5 semantics, I’d recommend checking out: HTML5 Semantic Elements and doing some Googling.

We now have a component that complies with SASS using Laravel Mix.

A Little More about Navigation.vue

So I added some styles to our Navigation.vue component. I’m going to preface these styles with this: this tutorial is focused on building a single page application with VueJS, Laravel and eventually transferring to mobile. I am NOT a CSS guru! Right now the styles will do and it shows how to use SASS variables with Vue components that compile with Laravel Mix.

<style lang="scss">
  @import '~@/abstracts/_variables.scss';

  nav.top-navigation{
    background-color: $white;
    height: 50px;
    border-bottom: 2px solid $dark-color;

    span.logo{
      border-right: 1px solid $dark-color;
      display: block;
      float: left;
      height: 50px;
      line-height: 50px;
      padding: 0px 20px 0px 20px;
      font-family: 'Josefin Sans', sans-serif;
      font-weight: bold;
      color: $dark-color;

      &:hover{
        color: white;
        background-color: $dark-color;
      }
    }

    ul.links{
      display: block;
      float: left;

      li{
        display: inline-block;
        list-style-type: none;
        line-height: 50px;

        a{
          font-family: 'Lato', sans-serif;
          font-weight: bold;
          color: $black;

          &:hover{
            color: $dark-color;
          }
        }
      }
    }

    div.right{
      float: right;

      img.avatar{
        width: 40px;
        height: 40px;
        border-radius: 40px;
        margin-top: 5px;
        margin-right: 10px;
      }
    }

  }
</style>

<template>
  <nav class="top-navigation">

    <router-link :to="{ name: 'home'}">
      <span class="logo">Roast And Brew</span>
    </router-link>

    <ul class="links">
      <li>
        <router-link :to="{ name: 'cafes' }">
          Cafes
        </router-link>
      </li>
    </ul>

    <div class="right">
      <img class="avatar" :src="user.avatar" v-show="userLoadStatus == 2"/>
    </div>

  </nav>
</template>

<script>
  export default {
    /*
      Defines the computed properties on the component.
    */
    computed: {
      /*
        Retrieves the User Load Status from Vuex
      */
      userLoadStatus(){
        return this.$store.getters.getUserLoadStatus;
      },

      /*
        Retrieves the User from Vuex
      */
      user(){
        return this.$store.getters.getUser;
      }
    }
  }
</script>

You will see a couple other things in the file such as <router-link> and some Vuex computed properties. We will touch on those in the next tutorial. I’m just showing some of the CSS I added.

We also added a few fonts that we will be using from Google Fonts in our resources/views/app.blade.php file:

<link href="https://fonts.googleapis.com/css?family=Lato:300,300i,400,400i,700,700i" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Josefin+Sans" rel="stylesheet">

We can use these fonts in our styles as well.

Conclusion

We now have a Vue component added to our our application that compiles SASS into the component using Laravel Mix. The next few tutorials will be cleaning up our app as we begin to add some unique functionality to the app.

Keep Reading
View the course View the Course API Driven Development With Laravel and VueJS
Up Next → Building a Page Layout for Vue Router

Support future content

The Ultimate Guide to Building APIs and Single-Page Applications with Laravel + VueJS + Capacitor book cover.

Psst... any earnings that we make off of our book is being reinvested to bringing you more content. If you like what you read, consider getting our book or get sweet perks by becoming a sponsor.

Written By Dan

Dan Pastori avatar Dan Pastori

Builder, creator, and maker. Dan Pastori is a Laravel certified developer with over 10 years experience in full stack development. When you aren't finding Dan exploring new techniques in programming, catch him at the beach or hiking in the National Parks.

Like this? Subscribe

We're privacy advocates. We will never spam you and we only want to send you emails that you actually want to receive. One-click unsubscribes are instantly honored.