Reader small image

You're reading from  Frontend Development Projects with Vue.js 3 - Second Edition

Product typeBook
Published inMar 2023
Reading LevelIntermediate
PublisherPackt
ISBN-139781803234991
Edition2nd Edition
Languages
Tools
Right arrow
Authors (4):
Maya Shavin
Maya Shavin
author image
Maya Shavin

Maya is Senior Software Engineer in Microsoft, working extensively with JavaScript and frontend frameworks and based in Israel. She holds a B.Sc in Computer Sciences, B.A in Business Management, and an International MBA from University of Bar-Ilan, Israel. She has worked with JavaScript and latest frontend frameworks such as React, Vue.js, etc to create scalable and performant front-end solutions at companies such as Cooladata and Cloudinary, and currently Microsoft. She founded and is currently the organizer of the VueJS Israel Meetup Community, helping to create a strong playground for Vue.js lovers and like-minded developers. Maya is also a published author, international speaker and an open-source library maintainer of frontend and web projects.
Read more about Maya Shavin

Raymond Camden
Raymond Camden
author image
Raymond Camden

Raymond Camden is a developer advocate for IBM. His work focuses on the MobileFirst platform, Bluemix, hybrid mobile development, Node.js, HTML5, and web standards in general. He is a published author and presents at conferences and user groups on a variety of topics. Raymond can be reached at his blog, on Twitter, or via email. He is the author of many development books, including Apache Cordova in Action and Client-Side Data Storage.
Read more about Raymond Camden

Clifford Gurney
Clifford Gurney
author image
Clifford Gurney

Clifford Gurney is a solution-focused and results-oriented technical lead at a series-A funded startup. A background in communication design and broad exposure to leading digital transformation initiatives enriches his delivery of conceptually designed front-end solutions using Vue JS. Cliff has presented at the Vue JS Melbourne meetups and collaborates with other like-minded individuals to deliver best in class digital experience platforms.
Read more about Clifford Gurney

Hugo Di Francesco
Hugo Di Francesco
author image
Hugo Di Francesco

Hugo Di Francesco is a software engineer who has worked extensively with JavaScript. He holds a MEng degree in mathematical computation from University College London (UCL). He has used JavaScript across the stack to create scalable and performant platforms at companies such as Canon and Elsevier and in industries such as print on demand and mindfulness. He is currently tackling problems in the travel industry at Eurostar with Node.js, TypeScript, React, and Kubernetes while running the eponymous Code with Hugo website. Outside of work, he is an international fencer, in the pursuit of which he trains and competes across the globe.
Read more about Hugo Di Francesco

View More author details
Right arrow

Styling components

When using Vue components, the Vite compiler allows you to use almost any frontend templating language style. The easiest way to enable these expressive library plugins in your Vue templates is to install them when you initialize your project, or by using npm install (or yarn add) for the package.

When using the style tag inside of a Vue component, you can specify a language using the lang attribute, provided that you have installed that specific language plugin.

For example, if you chose to install the Stylus preprocessor, first you need to install the stylus package in your project as a dependency by performing the following command:

npm add -D stylus
#OR
yarn add -d stylus

Then, you can add the lang="stylus" attribute to the style tag to begin using Stylus:

<style lang="stylus">
ul
  color: #2c3e50;
  > h2
  color: #22cc33;
</style>

Another benefit of using Vue is scoping the style with the scoped attribute. This is a useful way to create isolated and component-specific CSS stylings. It also overrides any other CSS global rules, according to the CSS rule of specificity.

It is not recommended to scope global styles. A common method for defining global styling is to separate these styles into another style sheet and import them into your App.vue file.

Now, let’s practice importing SCSS, a pre-processor plugin for CSS, to use in your application, and write some scoped stylings with the following exercise.

Exercise 1.11 – importing SCSS into a scoped component

In this exercise, we will be utilizing the style tag to add SCSS preprocessed styles to a component and importing external stylesheets.

To access the code file for this exercise, refer to https://github.com/PacktPublishing/Frontend-Development-Projects-with-Vue.js-3/tree/v2-edition/Chapter01/Exercise1.11.

Let’s start by performing the following steps:

  1. Use the application generated with npm init vue@3 as a starting point, or within the root folder of the code repository, navigate into the Chapter01/Exercise1.11 folder by using the following commands in order:
    > cd Chapter01/Exercise1.11/
    > yarn
  2. Run the application using the following command:
    yarn dev
  3. Open the exercise project in VS Code (by using the code . command within the project directory) or your preferred IDE.
  4. Create a new Vue component file named Exercise1-11.vue in the src/components directory.
  5. Inside Exercise1-11.vue, let’s write some HTML that can be styled using SCSS. Let’s keep practicing the interpolation method:
    <template>
      <div>
        <h1>{{ title }}</h1>
        <h2>{{ subtitle }}</h2>
        <ul>
          <li>{{ items[0] }}</li>
          <li>{{ items[1] }}</li>
          <li>{{ items[2] }}</li>
        </ul>
      </div>
    </template>
    <script>
    export default {
      data() {
        return {
          title: 'My list component!',
          subtitle: 'Vue JS basics',
          items: ['Item 1', 'Item 2', 'Item 3']
        }
      },
    }
    </script>
  6. Add the sass SCSS package as a project dependency:
    npm add -D sass
  7. Add the lang attribute to the style tag and add the scss value to enable SCSS syntax inside the style block:
    <style lang="scss"></style>
  8. Create a folder inside the src/ directory called styles. Inside this new folder, create a file called typography.scss:
    src/styles/typography.scss
  9. Inside typography.scss, add some styling for the template you composed in your component, such as defining color variables (green, grey, and blue) to reuse in different areas of related CSS rules, and some CSS styles for h1, h2, and the list elements:
    /* typography.scss */
    $color-green: #4fc08d;
    $color-grey: #2c3e50;
    $color-blue: #003366;
    h1 {
      margin-top: 60px;
      text-align: center;
      color: $color-grey;
      + h2 {
        text-align: center;
        color: $color-green;
      }
    }
    ul {
      display: block;
      margin: 0 auto;
      max-width: 400px;
      padding: 30px;
      border: 1px solid rgba(0,0,0,0.25);
      > li {
        color: $color-grey;
        margin-bottom: 4px;
      }
    }

In SCSS, you can use standard CSS selectors to select elements in your component.

ul > li will select every <li> element inside of an <ul> element for styling. Similarly, using the addition symbol (+) means that the elements placed after the first element will be styled if they match the condition. For example, h1 + h2 will dictate that all h2 elements after h1 will be styled in a certain way, but h3 will not. You can understand this better through the following example:

In CSS, you would present this code as follows:

h1 + h2 {
  /* Add styling */
}
ul > li {
  /* Add styling */
}

In SCSS, the same code can be represented as follows:

h1 {
  + h2 {
      // Add styling
  }
}
ul {
  > li {
      // Add styling
  }
}
  1. In your component, import these styles by using the SCSS @import method:
    <style lang="scss">
    @import '../styles/typography.scss';
    </style>

This will generate an output as follows:

Figure 1.40 – When you save and reload, your project should have the style imported

Figure 1.40 – When you save and reload, your project should have the style imported

  1. Add the scoped attribute to your <style> tag to only apply these styles to this component instance. Use the variable from the $color-blue imported stylesheet:
    <style lang="scss" scoped>
    @import '../styles/typography';
    h1 {
      font-size: 50px;
      color: $color-blue; // Use variables from imported stylesheets
    }
    </style>

The output of the preceding code is as follows:

Figure 1.41 – The outcome of scoping styles

Figure 1.41 – The outcome of scoping styles

  1. Inspect the DOM and you will notice that at runtime, that scoping has applied v-data-* attributes to your DOM elements specifying these specific rules.

The Elements tab of your browser Devtools also shows the following after expanding the <head> and <style> tags:

Figure 1.42 – How the virtual DOM uses data attributes to assign scoped styles

Figure 1.42 – How the virtual DOM uses data attributes to assign scoped styles

  1. Create a new style sheet called global.scss in the styles folder, containing only stylings for the main body element:
    /* /src/styles/global.scss */
    body {
        font-family: 'Avenir', Helvetica, Arial,
          sans-serif;
        margin: 0;
    }
  2. Import this stylesheet into your App.vue:
    <style lang="scss">
    @import './styles/global.scss';
    </style>

Our app should render the same as before; only the font family for all elements should change to Avenir and there should be no margin for the main body, as follows:

Figure 1.43 – Properly scoped styles for Exercise 1.03

Figure 1.43 – Properly scoped styles for Exercise 1.03

In this exercise, we interpolated data that originated from an array and learned about some basic SCSS syntax. Then, we styled our component using forms of scoped SCSS, which can either exist inside the <style> tag or be imported from another directory into our project.

In the next section, we are going to experiment with how to write dynamic CSS for a component using Vue 3 features.

Setting up state-driven dynamic CSS in Vue 3

Vue 3.x introduces a new CSS function, v-bind(), to use within the style section of a Vue SFC. We use this function to create a one-way link between local data and a CSS value.

Under the hood, the Vue engine uses CSS custom properties (or CSS variables) to compute the dynamic stylings received from v-bind(). For each v-bind(), it generates a hashed custom property (with the -- prefix) and adds it to the component’s root element. All the custom properties are added as inline static styles and will be updated whenever the linked local data’s value changes.

For example, let’s have a component that prints out a title and contains a local data property, headingStyles. The headingStyles data object contains several fields such as marginTop, textAlign, and color, indicating the relevant CSS properties:

<template>
<h1>{{ title }}</h1>
</template>
<script>
export default {
  data() {
    return {
      title: 'Binding with v-bind example',
        headingStyles: {
          marginTop: '10px',
          textAlign: 'center',
          : '#4fc08d',
        }
    }
  }
}
</script>

At this point, the output does not have a custom style and will be as follows:

Figure 1.44 – Displaying the title without using v-bind() and custom CSS

Figure 1.44 – Displaying the title without using v-bind() and custom CSS

We now can bind headingStyles to the CSS stylings of h1 in the <style> section, by applying v-bind() accordingly:

<style>
h1 {
  margin-top: v-bind(headingStyles.marginTop);
  text-align: v-bind(headingStyles.textAlign);
  color: v-bind(headingStyles.color);
}
</style>

The output will now have custom CSS enabled:

Figure 1.45 – Output with v-bind() and custom CSS applied

Figure 1.45 – Output with v-bind() and custom CSS applied

If you open Developer Tools and inspect this h1 element in the Elements tab, you will see it has inline styles, as shown in Figure 1.47:

Figure 1.46 – Devtools inspection shows the inline styles with hashed custom properties generated

Figure 1.46 – Devtools inspection shows the inline styles with hashed custom properties generated

Since v-bind() is a Vue 3.x feature, it also supports local variables defined using script setup out of the box. You can re-write the code in the script setup standards, and the outputs stay the same.

v-bind() also support JavaScript expressions. To use JavaScript expressions, you need to wrap them in quotes. For example, we can take headingStyles from the previous example and re-define marginTop as a number only:

headingStyles: {
  marginTop: 10,
  textAlign: 'center',
  color: '#4fc08d',
}

In the <style> section, let’s compute margin-top for the h1 selector with the addition of 5px and add the px suffix:

<style>
h1 {
  margin-top: v-bind('`${headingStyles.marginTop + 5}px`');
  text-align: v-bind(headingStyles.textAlign);
  color: v-bind(headingStyles.color);
}
</style>

The output now has a margin top of 15px as shown in Figure 1.48:

Figure 1.47 – Generated custom property for margin-top is 15px

Figure 1.47 – Generated custom property for margin-top is 15px

Using v-bind() is very beneficial for defining theming dynamically and programmatically. However, it provides only one-way binding from the local data to the styling, not vice versa. In the next section, we will explore the opposite binding direction using CSS modules.

Previous PageNext Page
You have been reading a chapter from
Frontend Development Projects with Vue.js 3 - Second Edition
Published in: Mar 2023Publisher: PacktISBN-13: 9781803234991
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €14.99/month. Cancel anytime

Authors (4)

author image
Maya Shavin

Maya is Senior Software Engineer in Microsoft, working extensively with JavaScript and frontend frameworks and based in Israel. She holds a B.Sc in Computer Sciences, B.A in Business Management, and an International MBA from University of Bar-Ilan, Israel. She has worked with JavaScript and latest frontend frameworks such as React, Vue.js, etc to create scalable and performant front-end solutions at companies such as Cooladata and Cloudinary, and currently Microsoft. She founded and is currently the organizer of the VueJS Israel Meetup Community, helping to create a strong playground for Vue.js lovers and like-minded developers. Maya is also a published author, international speaker and an open-source library maintainer of frontend and web projects.
Read more about Maya Shavin

author image
Raymond Camden

Raymond Camden is a developer advocate for IBM. His work focuses on the MobileFirst platform, Bluemix, hybrid mobile development, Node.js, HTML5, and web standards in general. He is a published author and presents at conferences and user groups on a variety of topics. Raymond can be reached at his blog, on Twitter, or via email. He is the author of many development books, including Apache Cordova in Action and Client-Side Data Storage.
Read more about Raymond Camden

author image
Clifford Gurney

Clifford Gurney is a solution-focused and results-oriented technical lead at a series-A funded startup. A background in communication design and broad exposure to leading digital transformation initiatives enriches his delivery of conceptually designed front-end solutions using Vue JS. Cliff has presented at the Vue JS Melbourne meetups and collaborates with other like-minded individuals to deliver best in class digital experience platforms.
Read more about Clifford Gurney

author image
Hugo Di Francesco

Hugo Di Francesco is a software engineer who has worked extensively with JavaScript. He holds a MEng degree in mathematical computation from University College London (UCL). He has used JavaScript across the stack to create scalable and performant platforms at companies such as Canon and Elsevier and in industries such as print on demand and mindfulness. He is currently tackling problems in the travel industry at Eurostar with Node.js, TypeScript, React, and Kubernetes while running the eponymous Code with Hugo website. Outside of work, he is an international fencer, in the pursuit of which he trains and competes across the globe.
Read more about Hugo Di Francesco