MDC-111 Web: Incorporating Material Components into your codebase (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

Material Components for the web (MDC Web) are framework-agnostic, built using regular JavaScript. This helps make MDC Web work seamlessly with your development process. These components can be installed as needed to help make agile design improvements in your existing app.

What you'll build

In this codelab, you'll replace some existing components in a form with ones provided by MDC Web:

c33f9d1388feca74.png

MDC Web components in this codelab

  • Button
  • Select
  • Text field

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

Download the starter codelab app

The starter app is located in the material-components-web-codelabs-master/mdc-111/starter directory. Be sure to cd into that directory before you start.

...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-111/starter

Install project dependencies

From the starter directory (material-components-web-codelabs/mdc-111/starter), run:

npm install

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

bb3a822c020c9287.png

Run the starter app

In the starter directory, run:

npm start

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

aa9263b15ae4f8d8.png

Success! You should see the app's shipping address form:

8f60906e660b695e.png

3. Update the button

Install MDC Button

Press Ctrl+C to kill the development server. Then, install the MDC Button NPM package and restart the server:

npm install @material/button
npm start

Import the CSS

At the top of _theme.scss, delete the .crane-button { ... } block, and add the following in its place:

$mdc-theme-primary: $crane-primary-color;

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

Update the markup

In index.html, remove the crane-button class from the <button> element, add the mdc-button and mdc-button--raised classes, and nest the label within a <span> element with the mdc-button__label class:

<button type="submit" class="mdc-button mdc-button--raised">
  <div class="mdc-button__ripple"></div>
  <span class="mdc-button__label">Save</span>
</button>

Add the ripple

MDC Buttons can be used without JavaScript. However, adding an interactive ripple to the button creates a richer user experience.

Press Ctrl+C to kill the development server. Then run:

npm install @material/ripple
npm start

Add the following import statement to the top of app.js:

import {MDCRipple} from '@material/ripple';

To instantiate the ripple on the button, add the following to the bottom of app.js:

new MDCRipple(document.querySelector('.mdc-button'));

Import Roboto font

By default, Material Design uses Roboto for component typefaces.

In index.html, import the Roboto Web font by adding the following to the <head> element:

<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700">

Reload the page, and you should see something like this:

9be8eb813b02eada.gif

The button now displays subtle ripple effect as visual feedback when pressed.

4. Update the select element

The MDC Select component wraps a native HTML <select> element. Use it wherever you would normally use a <select>. Let's update the "State" field.

Install MDC Node module

Press Ctrl+C to kill the development server. Then run:

npm install @material/select
npm start

Import the CSS

Add the following to _theme.scss, just after the button import:

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

Update markup

Locate the <select> element in index.html. Replace the crane-input class with mdc-select__native-control:

<select class="mdc-select__native-control" id="crane-state-input" required>

Right above the <select> tag, add the following markup for the MDC Select component's drop-down arrow:

<i class="mdc-select__dropdown-icon"></i>

Just below the closing </select> tag, replace the crane-label class with mdc-floating-label:

<label class="mdc-floating-label" for="crane-state-input">

Then add the following markup immediately after the label:

<div class="mdc-line-ripple"></div>

Finally, add the following tags around the <select> element (but inside the crane-field element):

<div class="mdc-select">
  ...
</div>

The resulting markup should look like this:

<div class="crane-field">
  <div class="mdc-select">
    <i class="mdc-select__dropdown-icon"></i>
    <select class="mdc-select__native-control" id="crane-state-input" required>
      <option value="" selected></option>
      <option value="AL">Alabama</option>
      ...
      <option value="WI">Wisconsin</option>
      <option value="WY">Wyoming</option>
    </select>
    <label class="mdc-floating-label" for="crane-state-input">
      State
    </label>
    <div class="mdc-line-ripple"></div>
  </div>
</div>

Import the JS

Add the following import statement to the top of app.js:

import {MDCSelect} from '@material/select';

To instantiate the select, add the following to the bottom of app.js:

new MDCSelect(document.querySelector('.mdc-select'));

Reload the page, which should now look like this:

20fa4104564f8195.gif

The MDC Select component presents a list of options for the user in a familiar format, but with modern styling.

5. Update the text fields

Material Design text fields have major usability gains over plain <input> elements. They are designed to be easy to identify within complicated content, and display subtle visual feedback when the user interacts with them.

Install MDC Node module

Press Ctrl+C to kill the development server. Then run:

npm install @material/textfield
npm start

Add the CSS

Add the following to _theme.scss, just after the select import:

@import "@material/textfield/mdc-text-field";

Update the markup

In index.html, locate the <input> element for the "Name" field. Replace the crane-input class with mdc-text-field__input:

<input class="mdc-text-field__input" id="crane-name-input" type="text" required autofocus>

Next, replace the crane-label class with mdc-floating-label:

<label class="mdc-floating-label" for="crane-name-input">

Then add the following markup immediately after the label:

<div class="mdc-line-ripple"></div>

Finally, wrap all 3 elements with the following:

<div class="mdc-text-field">
  ...
</div>

The resulting markup should look like this:

<div class="crane-field">
  <div class="mdc-text-field">
    <input class="mdc-text-field__input" id="crane-name-input"
           type="text" required autofocus>
    <label class="mdc-floating-label" for="crane-name-input">
      Name
    </label>
    <div class="mdc-line-ripple"></div>
  </div>
</div>

Repeat the same procedure for all other <input> elements on the page.

The markup for the "Address", "City" and "ZIP Code" fields should look like this:

<div class="crane-field">
  <div class="mdc-text-field">
    <input class="mdc-text-field__input" id="crane-address-input" type="text" required>
    <label class="mdc-floating-label" for="crane-address-input">
      Address
    </label>
    <div class="mdc-line-ripple"></div>
  </div>
</div>
<div class="crane-field">
  <div class="mdc-text-field">
    <input class="mdc-text-field__input" id="crane-city-input" type="text" required>
    <label class="mdc-floating-label" for="crane-city-input">
      City
    </label>
    <div class="mdc-line-ripple"></div>
  </div>
</div>
<div class="crane-field">
  <div class="mdc-text-field">
    <input class="mdc-text-field__input" id="crane-zip-code-input"
            type="text" required minlength="5" maxlength="5" pattern="[0-9]*">
    <label class="mdc-floating-label" for="crane-zip-code-input">
      ZIP Code
    </label>
    <div class="mdc-line-ripple"></div>
  </div>
</div>

You can now remove the .crane-label and .crane-input styles from _theme.scss, which are no longer used.

Import the JS

Add the following import statement to the top of app.js:

import {MDCTextField} from '@material/textfield';

To instantiate the text fields, add the following to the bottom of app.js:

const textFieldElements = [].slice.call(document.querySelectorAll('.mdc-text-field'));
textFieldElements.forEach((textFieldEl) => {
  new MDCTextField(textFieldEl);
});

Reload the page, which should now look like this:

c33f9d1388feca74.png

The text fields have now all been updated to use Material Theming.

6. Recap

You've replaced some common components (text fields, select, and button) without doing a complete redesign of your app. Great job!

Other components that can also make a big difference include the top app bar and navigation drawer.

Next steps

You can explore even more components in MDC Web by visiting the MDC Web catalog.

If you are interested in using MDC Web with a particular framework, head over to MDC-112: Integrating MDC with Web Frameworks.

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