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.
In this codelab, you'll replace some existing components in a form with ones provided by MDC Web:
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.
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
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:
In the starter directory, run:
npm start
The webpack-dev-server
will start. Point your browser to http://localhost:8080/ to see the page.
Success! You should see the app's shipping address form:
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
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";
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>
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'));
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:
The button now displays subtle ripple effect as visual feedback when pressed.
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.
Press Ctrl
+C
to kill the development server. Then run:
npm install @material/select npm start
Add the following to _theme.scss
, just after the button import:
@import "@material/select/mdc-select";
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>
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:
The MDC Select component presents a list of options for the user in a familiar format, but with modern styling.
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.
Press Ctrl
+C
to kill the development server. Then run:
npm install @material/textfield npm start
Add the following to _theme.scss
, just after the select import:
@import "@material/textfield/mdc-text-field";
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.
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:
The text fields have now all been updated to use Material Theming.
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.
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.