MDC-103 Web: Material Theming with Color, Shape, Elevation and Type (Web)

1. Introduction

logo_components_color_2x_web_96dp.png

Material Components (MDC) help developers implement Material Design. Created by a team of engineers and UX designers at Google, MDC features dozens of beautiful and functional UI components and is available for Android, iOS, web and Flutter.material.io/develop

In codelabs MDC-101 and MDC-102, you used Material Components (MDC) to build the basics of an app called Shrine, an e-commerce app that sells clothing and home goods. This app's user flow starts with a login screen, which then takes the user to a home screen containing products.

Material Design recently expanded to give designers and developers increased flexibility to express their product's brand. In this code lab, you'll use MDC to customize the Shrine app to reflect the brand's unique style in more ways than ever before.

What you'll build

In this codelab, you'll customize Shrine to reflect its brand using:

  • Color
  • Typography
  • Elevation
  • Shape
  • Layout

9c51661824dfa934.png

MDC Web components and subsystems used in this codelab

  • Theme
  • Typography
  • Elevation
  • Image list

What you'll need

  • A recent version of Node.js (which comes bundled with npm, a JavaScript package manager).
  • The sample code (to be downloaded in the next step)
  • Basic knowledge of HTML, CSS, and JavaScript

How would you rate your level of experience with web development?

Novice Intermediate Proficient

2. Set up your development environment

Continuing from MDC-102?

If you completed MDC-102, your code should be ready to go for this codelab. Skip to step 3: Change the color.

Download the starter codelab app

The starter app is located within the material-components-web-codelabs-master/mdc-103/starter directory. Be sure to cd into that directory before beginning.

...or clone it from GitHub

To clone this codelab from GitHub, run the following commands:

git clone https://github.com/material-components/material-components-web-codelabs
cd material-components-web-codelabs/mdc-103/starter

Install project dependencies

From the starter directory material-components-web-codelabs/mdc-103/starter (it should be your current directory if you follow the above step), run:

npm install

You will see a lot of activity and at the end, your terminal should show a successful install:

23003b0e5fdf9077.png

Run the starter app

In the same directory, run:

npm start

The webpack-dev-server will start. Point your browser to http://localhost:8080/ to see the page.

61dc5a089bf0986b.png

Success! You should see Shrine's login page running in your browser. Fill in the Username and Password fields, and click the "Next" button to go to the home page. It should display a navigation drawer on the left, next to a grid of product images.

e2f359c254988d75.png

While the navigation drawer is functional, let's make it match the Shrine brand by changing its color, elevation, and typography.

3. Change the color

This color theme has been created by a designer with custom colors (shown in the image below). It contains colors that have been selected from Shrine's brand and applied to the Material Theme Editor, which has expanded them to create a fuller palette. (These colors aren't from the 2014 Material color palettes.)

Let's change the color of the Shrine app's navigation drawer to reflect that color scheme.

Override the theme colors

Create a new file named _variables.scss, containing the following:

$mdc-theme-primary: #FEDBD0;
$mdc-theme-on-primary: #442C2E;
$mdc-theme-secondary: #FEEAE6;
$mdc-theme-on-secondary: #442C2E;
$mdc-theme-surface: #FFFBFA;
$mdc-theme-on-surface: #442C2E;
$mdc-theme-background: #FFFFFF;
$mdc-theme-on-background: #442C2E;

Then import it at the very top of _common.scss:

@import "./variables";

Add CSS styling to the navigation drawer

In home.scss, add the following import statement after the existing imports:

@import "@material/ripple/mixins";

Then add the following styles, creating the .shrine-drawer class:

.shrine-drawer {
  @include mdc-drawer-fill-color-accessible(primary);
  // Drawer defaults to a higher z-index, but we aren't overlaying it over anything
  @include mdc-drawer-z-index(0);

  text-transform: uppercase;

  .mdc-list {
    margin: 70px 5px auto 5px;
  }

  .mdc-list-item {
    border-radius: 6px;
    justify-content: center;
  }

  // This needs 3-class specificity to override MDC Drawer styles
  .mdc-list .mdc-list-item {
    @include mdc-states-activated(#fff);
  }
}

Refresh the page at http://localhost:8080/home.html. Your home screen should now look like this:

816105f1c5a033f2.png

Let's change the color of the login screen to match our color scheme.

Add CSS styling to the login page

In login.scss, add the following lines:

.shrine-login {
  background-color: $mdc-theme-background;
  color: $mdc-theme-on-background;
}

.cancel {
  @include mdc-button-ink-color(on-primary);
}

Also, add the following mixin invocations inside the .username, .password CSS selector:

.username,
.password {
  &:not(.mdc-text-field--invalid) {
    @include mdc-text-field-label-color(on-primary);
  }
  &.mdc-text-field--focused:not(.mdc-text-field--invalid)  {
    @include mdc-text-field-label-color(on-primary);
  }
  ...
}

Refresh the page at http://localhost:8080/. Your login screen should now look like this:

9e0172a18582a44e.png

4. Modify typography and label styles

In addition to color changes, your designer has also given you specific typography to use on the site. Let's add that to the navigation drawer too.

To install the package for Typography, run:

npm install @material/typography

Add the CSS for typography

In home.scss, add the following import statement after the existing imports:

@import "@material/typography/mdc-typography";

Then add the following mixin invocation to the shrine-title class:

.shrine-title {
  @include mdc-typography(headline6);
  ...
}

Next, let's style the drawer items.

Add a line separator

In home.html, add the following immediately after the <a ...>Featured</a> element:

<div class="shrine-select-item-divider mdc-list-divider" role="separator"></div>

Add the following styles to home.scss:

.shrine-select-item-divider {
  display: block;
  border-bottom-color: #EAA4A4;
  border-bottom-width: 2px;
  width: 50px;
  position: relative;
  top: -8px;
}

// This needs 2-class specificity to override MDC Drawer styles
.shrine-drawer .shrine-select-item-divider {
  margin: 0 auto;
}

Adjust the image items and labels

To adjust the items and labels, add the following styles to home.scss within the .product-list selector:

.product-list {
  ...

  .mdc-image-list__supporting {
    justify-content: center;
  }

  .mdc-image-list__item {
    padding: 10px;
  }

  .mdc-image-list__label {
    @include mdc-typography(subtitle2);
  }
}

Refresh the page. Your home screen should now look like this:

129ada72a02baf5a.png

5. Adjust elevation

Now that you've styled the page with Shrine's specific coloring and typography, let's look at the image list showing Shrine's products. Let's draw attention to the products by giving them more emphasis.

To install the package for Elevation, run:

npm install @material/elevation

Add the import statement

In home.scss, add the following line after the last import statement:

@import "@material/elevation/mdc-elevation";

Wrap the image list with a new div

In home.html, add the following markup around the <ul> element:

<div class="shrine-body">
 <ul...>
</div>

Change elevation using Sass mixins

In home.scss, add the following:

.shrine-body {
  @include mdc-elevation(4);

  display: block;
  overflow: auto;
  z-index: 0; // Elevate over the drawer
}

Impressive! You've added a shadow to the left edge of the white surface behind the image list items, so that it appears to float slightly above the navigation.

66c3d6a82fb8bb23.png

6. Change the layout

Next, let's change the layout to show images at different aspect ratios and sizes, so that each image looks unique against the others.

Modify the HTML

In home.html, update the mdc-image-list element to contain the mdc-image-list--masonry class:

<ul class="mdc-image-list mdc-image-list--masonry product-list">

Add images

In home.html, change each img element's src attribute to match the images located in the assets folder. Then, update the label text for each image. When completed, it should look like this:

    <ul class="mdc-image-list mdc-image-list--masonry product-list">
      <li class="mdc-image-list__item">
        <img class="mdc-image-list__image" src="assets/ginger-scarf.jpg">
        <div class="mdc-image-list__supporting">
          <span class="mdc-image-list__label">Ginger scarf</span>
        </div>
      </li>
      <li class="mdc-image-list__item">
        <img class="mdc-image-list__image" src="assets/blue-stone-mug.jpg">
        <div class="mdc-image-list__supporting">
          <span class="mdc-image-list__label">Blue stone mug</span>
        </div>
      </li>
      <li class="mdc-image-list__item">
        <img class="mdc-image-list__image" src="assets/cerise-scallop.jpg">
        <div class="mdc-image-list__supporting">
          <span class="mdc-image-list__label">Cerise scallop tee</span>
        </div>
      </li>
      <li class="mdc-image-list__item">
        <img class="mdc-image-list__image" src="assets/chambray-napkins.jpg">
        <div class="mdc-image-list__supporting">
          <span class="mdc-image-list__label">Chambray napkins</span>
        </div>
      </li>
      <li class="mdc-image-list__item">
        <img class="mdc-image-list__image" src="assets/fine-lines.jpg">
        <div class="mdc-image-list__supporting">
          <span class="mdc-image-list__label">Fine lines tee</span>
        </div>
      </li>
      <li class="mdc-image-list__item">
        <img class="mdc-image-list__image" src="assets/garden-strand.jpg">
        <div class="mdc-image-list__supporting">
          <span class="mdc-image-list__label">Garden strand</span>
        </div>
      </li>
      <li class="mdc-image-list__item">
        <img class="mdc-image-list__image" src="assets/gatsby-hat.jpg">
        <div class="mdc-image-list__supporting">
          <span class="mdc-image-list__label">Gatsby hat</span>
        </div>
      </li>
      <li class="mdc-image-list__item">
        <img class="mdc-image-list__image" src="assets/gilt-desk-trio.jpg">
        <div class="mdc-image-list__supporting">
          <span class="mdc-image-list__label">Gilt desk trio</span>
        </div>
      </li>
      <li class="mdc-image-list__item">
        <img class="mdc-image-list__image" src="assets/kitchen-quattro.jpg">
        <div class="mdc-image-list__supporting">
          <span class="mdc-image-list__label">Kitchen quattro</span>
        </div>
      </li>
      <li class="mdc-image-list__item">
        <img class="mdc-image-list__image" src="assets/seabreeze-sweater.jpg">
        <div class="mdc-image-list__supporting">
          <span class="mdc-image-list__label">Seabreeze sweater</span>
        </div>
      </li>
      <li class="mdc-image-list__item">
        <img class="mdc-image-list__image" src="assets/shrug-bag.jpg">
        <div class="mdc-image-list__supporting">
          <span class="mdc-image-list__label">Shrug bag</span>
        </div>
      </li>
      <li class="mdc-image-list__item">
        <img class="mdc-image-list__image" src="assets/stella-sunglasses.jpg">
        <div class="mdc-image-list__supporting">
          <span class="mdc-image-list__label">Stella sunglasses</span>
        </div>
      </li>
      <li class="mdc-image-list__item">
        <img class="mdc-image-list__image" src="assets/surf-and-perf.jpg">
        <div class="mdc-image-list__supporting">
          <span class="mdc-image-list__label">Surf and perf shirt</span>
        </div>
      </li>
      <li class="mdc-image-list__item">
        <img class="mdc-image-list__image" src="assets/vagabond-sack.jpg">
        <div class="mdc-image-list__supporting">
          <span class="mdc-image-list__label">Vagabond sack</span>
        </div>
      </li>
      <li class="mdc-image-list__item">
        <img class="mdc-image-list__image" src="assets/walter-henley.jpg">
        <div class="mdc-image-list__supporting">
          <span class="mdc-image-list__label">Walter henley (white)</span>
        </div>
      </li>
      <li class="mdc-image-list__item">
        <img class="mdc-image-list__image" src="assets/weave-keyring.jpg">
        <div class="mdc-image-list__supporting">
          <span class="mdc-image-list__label">Weave keyring</span>
        </div>
      </li>
    </ul>

Update the CSS

In home.scss, remove the mdc-image-list-standard-columns(4) mixin and replace it with the following mixin:

@include mdc-image-list-masonry-columns(4);

Then add the following padding values to the product-list class in home.scss:

.product-list {
  ...
  padding: 80px 100px 0;
}

9c51661824dfa934.png

Your code should now match the code included in the complete/ folder.

7. Try another theme

Color is a powerful way to express your brand, and a small change in color can have a large effect on your user experience. To test this out, let's see what Shrine would look like if the color scheme of the brand were completely different.

Modify CSS

In _variables.scss, replace the variables you declared for the primary theme with the following:

$mdc-theme-primary: #5D1049;
$mdc-theme-on-primary: #FFFFFF;
$mdc-theme-secondary: #E30425;
$mdc-theme-on-secondary: #FFFFFF;
$mdc-theme-surface: #FFFFFF;
$mdc-theme-on-surface: #000000;
$mdc-theme-background: #F4E2ED;
$mdc-theme-on-background: #000000;

In login.scss, remove the mixins in the .username, .password selector. It should look like the following:

.username,
.password {
  display: block;
  width: 300px;
  margin: 20px auto;
}

Additionally, remove the mdc-button-ink-color mixin override in the .cancel class:

In home.scss, add the following rule to the .home class:

background-color: $mdc-theme-background;

Within the .shrine-logo-drawer selector, replace the fill property to be the on-primary color:

.shrine-logo-drawer {
  ...
  fill: $mdc-theme-on-primary;
}

Similarly, within the .shrine-title selector set the color property to be the on-primary color:

.shrine-title {
  ...
  color: $mdc-theme-on-primary;
}

Finally, remove the mdc-elevation mixin used earlier under the .shrine-body selector.

Build and run. The new theme should now appear in your browser.

7fdf830a944e53d7.png

Now navigate to http://localhost:8080/home.html to see changes to the home.html page.

7369127decb1a875.png

8. Recap

You've now created an app that resembles your designer's specifications.

Next steps

You've now used the following MDC components: theme, typography, elevation, and shape. You can explore more components and subsystems in the MDC Web Catalog.

I was able to complete this codelab with a reasonable amount of time and effort

Strongly agree Agree Neutral Disagree Strongly disagree

I would like to continue using Material Components in the future

Strongly agree Agree Neutral Disagree Strongly disagree