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

What are Material Design and Material Components for the Web?

Material Design is a system for building bold and beautiful digital products. By uniting style, branding, interaction, and motion under a consistent set of principles and components, product teams can realize their greatest design potential.

For desktop and the mobile web, Material Components Web (MDC Web) unites design and engineering with a library of components for creating consistency across apps and websites. As the Material Design system evolves, these components are updated to ensure consistent pixel-perfect implementation and adherence to Google's front-end development standards. MDC is also available for Android, iOS, and Flutter.

In this codelab, you'll build a login page using several of MDC Web's components.

What you'll build

This codelab is the first of three codelabs that will guide you through building an app called Shrine, an e-commerce website that sells clothing and home goods. It will demonstrate how you can customize components to reflect any brand or style using MDC Web.

In this codelab, you'll build a login page for Shrine that contains:

MDC Web components in this codelab

What you'll need

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

Novice Intermediate Proficient

Download the starter codelab app

Download starter app

The starter app is located within the material-components-web-codelabs-master/mdc-101/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-101/starter

Install project dependencies

From the starter directory, run:

npm install

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

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.

Success! The starter code for Shrine's login page should be running in your browser. You should see the name "Shrine" and the Shrine logo just below it.

Take a look at the code

Metadata in index.html

In the starter directory, open index.html with your favorite code editor. It should contain this:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <title>Shrine (MDC Web Example App)</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" sizes="192x192" href="https://material.io/static/images/simple-lp/favicons/components-192x192.png">
  <link rel="shortcut icon" href="https://material.io/static/images/simple-lp/favicons/components-72x72.png">

  <link rel="stylesheet"
        href="https://cdnjs.cloudflare.com/ajax/libs/normalize/6.0.0/normalize.min.css">
  <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet">
  <link rel="stylesheet" href="bundle.css">
</head>
<body class="shrine-login">
  <section class="header">
    <svg class="shrine-logo" ...>
      ...
    </svg>
    <h1>SHRINE</h1>
  </section>

  <form action="home.html">
  </form>

  <script src="bundle.js" async></script>
</body>
</html>

Here, a <link> tag is used to load the bundle.css file which was generated by webpack, and a <script> tag includes the bundle.js file. In addition, we include normalize.css for consistent cross-browser rendering, as well as the Roboto font from Google Fonts.

Custom styles in app.scss

MDC Web components are styled using mdc-* CSS classes, such as the class mdc-text-field. (MDC Web treats its DOM structure as part of its public API.)

In general, it's recommended that you make custom style modifications to components using your own classes. You might have noticed some custom CSS classes in the HTML above, such as shrine-logo. These styles are defined in app.scss to add basic styles to the page.

Open app.scss and you'll see the following styles for the login page:

// Login page styles

.header {
  text-align: center;
}

.shrine-logo {
  width: 150px;
  height: 150px;
  padding-top: 80px;
  fill: currentColor;
}

Now that you're familiar with the starter code, let's implement our first component.

To begin, we'll add two text fields to our login page, where people will be able to enter their username and password. We'll use the MDC Text Field component, which includes built-in functionality that displays a floating label and activates a touch ripple.

Install the MDC Text Field

MDC Web components are published via NPM packages. To install the package for the text field component, run:

npm install @material/textfield

Add the HTML

In index.html, add the following inside the <form> element in the body:

<div class="mdc-text-field mdc-text-field--box username">
  <input type="text" class="mdc-text-field__input" id="username-input" name="username">
  <label class="mdc-floating-label" for="username-input">Username</label>
  <div class="mdc-line-ripple"></div>
</div>
<div class="mdc-text-field mdc-text-field--box password">
  <input type="password" class="mdc-text-field__input" id="password-input" name="password">
  <label class="mdc-floating-label" for="password-input">Password</label>
  <div class="mdc-line-ripple"></div>
</div>

The MDC Text Field API is composed of several parts:

In addition, we're using a style variant called box, which is indicated by the mdc-text-field--box class.

Add the CSS

At the top of app.scss, add the following import statement:

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

In the same file, add the following styles under // Login page styles to align and center the text fields:

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

Add the JavaScript

Open up app.js, which is currently empty. Add the following code to import and instantiate the Text Fields:

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

const username = new MDCTextField(document.querySelector('.username'));
const password = new MDCTextField(document.querySelector('.password'));

Add HTML5 validation

Text Fields express if the field input is valid or contains an error, by using attributes provided by HTML5's form validation API.

You should:

Adjust the two <div class="mdc-text-field"> elements to look like this:

<div class="mdc-text-field mdc-text-field--box username">
  <input type="text" class="mdc-text-field__input" id="username-input" name="username" required>
  <label class="mdc-floating-label" for="username-input">Username</label>
  <div class="mdc-line-ripple"></div>
</div>
<div class="mdc-text-field mdc-text-field--box password">
  <input type="password" class="mdc-text-field__input" id="password-input" name="password" required minlength="8">
  <label class="mdc-floating-label" for="password-input">Password</label>
  <div class="mdc-line-ripple"></div>
</div>

Refresh the page at http://localhost:8080/. You should now see a page with two text fields for Username and Password!

Click on the text fields to check out the floating label animation and the line ripple animation (the bottom border line that ripples outwards):

Next, we'll add two buttons to our login page: "Cancel" and "Next." We'll use the MDC Button component, along with the MDC Ripple component, to complete the iconic Material Design ink ripple effect.

Install MDC Button

To install the package for the button component, run:

npm install @material/button

Add the HTML

In index.html, add the following below the <div class="mdc-text-field mdc-text-field--box password"> element:

<div class="button-container">
  <button type="button" class="mdc-button cancel">
    Cancel
  </button>
  <button class="mdc-button mdc-button--raised next">
    Next
  </button>
</div>

For the "Cancel" button, we're using the default button style. However, the "Next" button uses a raised style variant, which is indicated by the mdc-button--raised class.

To easily align them later, we wrap the two mdc-button elements in a <div> element.

Add the CSS

At the top of app.scss, add the following import statement:

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

To align the buttons and add a margin around them, add the following styles to app.scss under // Login page styles:

.button-container {
  display: flex;
  justify-content: flex-end;
  width: 300px;
  margin: auto;
}

.button-container button {
  margin: 3px;
}

Add an ink ripple to the buttons

When the user touches or clicks a button, it should display feedback in the form of an ink ripple. The ink ripple component requires JavaScript, so we'll add that to the page.

At the top of app.js, add the following import statement:

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

To instantiate the ripples, add the following to app.js:

new MDCRipple(document.querySelector('.cancel'));
new MDCRipple(document.querySelector('.next'));

Because we don't need to retain a reference to the ripple instance, there's no need to assign it to a variable.

That's it! Refresh the page. An ink ripple will display when you click each button.

Fill in the text fields with valid values, and press the "NEXT" button. You did it! You'll continue working on this page in MDC-102.

Using basic HTML markup and just a few lines of CSS and JavaScript, the Material Components for the web library has helped you create a beautiful login page that conforms to the Material Design guidelines, and looks and behaves consistently across all devices.

Next steps

Text Field and Button are two core components in the MDC Web library, but there are many more! You can also explore the rest of the components in MDC Web.

You can head over to MDC-102: Material Design Structure and Layout to learn about the navigation drawer and image list. Thanks for trying Material Components. We hope you enjoyed this codelab!

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