These guidelines are for writing flexible, consistent and maintainable HTML and CSS.
</li>
or </body>
). <!doctype html>
<html>
<head>
<title>Page title</title>
</head>
<body>
<img src="images/logo.png" alt="Company">
<h1 class="hello-world">Hello, world!</h1>
</body>
</html>
Use standards mode rendering for more consistent rendering across browsers. Keep it lowercase.
<!doctype html>
Use a lang attribute. This helps speech and language tools choose which rules to use.
<html lang="en">
Only if you need support for IE10 and older.
<!-- IE10 and below only -->
<meta http-equiv="x-ua-compatible" content="ie=edge">
Used to determine the correct rendering of characters. Allows you to use —
instead of &emdash;
for example.
UTF-8 is the recommended.
<head>
<meta charset="utf-8">
</head>
<body>
<p>Use an em dash like this — instead of an HTML entity.</p>
</body>
No need to specify type
when you include CSS or JavaScript. text/css
and text/javascript
are taken as defaults.
<!-- Include CSS -->
<link rel="stylesheet" href="main.css">
<!-- Inline CSS -->
<style>
/* ... */
</style>
<!-- Include JavaScript -->
<script src="main.js"></script>
Use semantic html, but be pragmatic. Prefer the option that gives the least amount of code with the fewest intricacies.
<!-- Good -->
<button>...</button>
<!-- Less good -->
<div class="btn" onClick="...">...</div>
A boolean attribute is one that does not need to have a declared value. XHTML did require a value, but HTML5 does not.
The presence of a boolean attribute on an element represents true, and the absence of the attribute represents false.
Basically, don’t add a value.
Good
<input type="text" disabled>
<input type="checkbox" value="1" checked>
<select>
<option value="1" selected>1</option>
</select>
Bad
<input type="text" disabled="true">
<input type="checkbox" value="1" checked="false">
<select>
<option value="1" selected="true">1</option>
</select>
Avoid unnecessary parent elements.
<!-- Bad -->
<span class="avatar">
<img src="...">
</span>
<!-- Good -->
<img class="avatar" src="...">
Settings for your code editor to avoid inconsistencies and messy merges/diffs:
:
..5
instead of 0.5
and -.5px
instead of -0.5px
).#fff
. Lowercase is easier to read when scanning.#fff
instead of #ffffff
.margin: 0;
instead of margin: 0px;
. // Bad
.selector, .selector-secondary, .selector[type=text] {
padding:15px;
margin:0px 0px 15px;
background-color:rgba(0, 0, 0, 0.5);
box-shadow:0px 1px 2px #CCC,inset 0 1px 0 #FFFFFF
}
// Good
.selector,
.selector-secondary,
.selector[type="text"] {
padding: 15px;
margin-bottom: 15px;
background-color: rgb(0 0 0 / .5);
box-shadow: 0 1px 2px #ccc, inset 0 1px 0 #fff;
}
Property declarations should be grouped together with the this order:
Positioning first as it can remove an element from the document flow and override any box model related styles.
Whether it’s flex, float, grid, or table, then follows as it determines a component’s dimensions, placement, and alignment.
Everything else occurs inside the component or without affecting the previous two sections, so they come last.
.declaration-order {
// Positioning
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 100;
// Box model
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100px;
height: 100px;
// Typography
font: normal 14px "Helvetica Neue", sans-serif;
line-height: 1.5;
color: #333;
text-align: center;
text-decoration: underline;
// Visual
background-color: #f5f5f5;
border: 1px solid #e5e5e5;
border-radius: 3px;
// Misc
opacity: 1;
}
Logical properties are the alternatives to directional and dimensonal properties which are based on more abstract terms like block and inline.
By default, block applies to the vertical direction (top and bottom) while inline refers to the horizontal direction (right and left).
Not every language flows left-ro-right like English, so the writing mode should be flexible. Using logical properties makes it easier to support these languages.
// Without logical properties
.element {
margin-right: auto;
margin-left: auto;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
}
// With logical properties
.element {
margin-inline: auto;
border-block: 1px solid #eee;
}
Use rgba()
and hsla()
instead for rgb()
and hsl()
.
.element {
color: rgb(255 255 255 / .65);
background-color: rgb(0 0 0 / .95);
}
@import
s@import
s are slower than <link>
s, they add additional page requests. Avoid them and instead use:
<link>
elements <!-- Use link elements -->
<link rel="stylesheet" href="core.css">
<!-- Avoid @imports -->
<style>
@import url("more.css");
</style>
Put your media queries close to their related rule sets.
.element { ... }
.element-avatar { ... }
.element-selected { ... }
@media (min-width: 480px) {
.element { ... }
.element-avatar { ... }
.element-selected { ... }
}
When a rule has only one declaration, remove any line breaks for better readability and editing.
// Single declarations on one line
.span1 { width: 60px; }
.span2 { width: 140px; }
.span3 { width: 220px; }
// Multiple declarations, one per line
.sprite {
display: inline-block;
width: 16px;
height: 15px;
background-image: url("../img/sprite.png");
}
.icon { background-position: 0 0; }
.icon-home { background-position: 0 -20px; }
.icon-account { background-position: 0 -40px; }
Limit shorthand declarations to those cases where you need to set all the available values.
padding
margin
font
background
border
border-radius
Using shorthand properties can lead to more verbose code with unnecessary overrides and unpredictable side effects.
// Bad
.element {
margin: 0 0 10px;
background: red;
background: url("image.jpg");
border-radius: 3px 3px 0 0;
}
// Good
.element {
margin-bottom: 10px;
background-color: red;
background-image: url("image.jpg");
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
Avoid nesting in preprocessors. Keep it simple.
// Without nesting clear
.table > thead > tr > th { … }
.table > thead > tr > td { … }
// With nesting confusing
.table > thead > tr {
> th { … }
> td { … }
}
Wrap all operations in parentheses.
// Bad
.element {
margin: 10px 0 @variable*2 10px;
}
// Good
.element {
margin: 10px 0 (@variable * 2) 10px;
}
Code is written for people. It should be descriptive, well commented, and accessible to others.
Good comments convey context and purpose.
// Bad
// Modal header
.modal-header {
...
}
// Good
// Wrapping element for .modal-title and .modal-close
.modal-header {
...
}
.btn
and .btn-danger
)..btn
is useful for button, but .s
doesn’t mean anything..js-*
classes to indicate behavior. // Bad
.t { ... }
.red { ... }
.header { ... }
// Good
.tweet { ... }
.important { ... }
.tweet-header { ... }
[class^="..."]
) on commonly occuring components. Browser performance is impacted.only
when necessary. // Bad
span { ... }
.page-container #stream .stream-item .tweet .tweet-header .username { ... }
.avatar { ... }
// Good
.avatar { ... }
.tweet-header .username { ... }
.tweet .avatar { ... }
Use the child combinator >
to limit the cascade of styles used with elements like <table>
s that can be deeply nested.
.custom-table > tbody > tr > td,
.custom-table > tbody > tr > th {
/* ... */
}
//
// Component section heading
//
.element { ... }
//
// Component section heading
//
// Sometimes you need to include optional context for the entire component. Do that up here if it's important enough.
//
.element { ... }
// Contextual sub-component or modifer
.element-heading { ... }