In web development, HTML forms the basic skeletal structure, and CSS decides how the markup language will be presented. Both are closely related to service performance and accessibility. In other words, both HTML and CSS must be written well in order for all browsers to fully express the contents without significant loss. This guide serves to help developers write consistent codes to facilitate cooperation and to minimize maintenance and expansion cost.
<link>
instead of @import
.Use two empty spaces to indent.
<!-- Bad -->
<table>
<tr>
<th>Name</th>
<th>Favorite Color</th>
</tr>
...
</table>
<!-- Good -->
<table>
<tr>
<th>Name</th>
<th>Favorite Color</th>
</tr>
...
</table>
Use double quotation marks (""
) for attribute values.
<!-- Bad -->
<a href='/' class='home'>Home</a>
<!-- Good -->
<a href="/" class="home">Home</a>
Only use lowercase for tag names, attribute names, and attribute values.
<!-- Bad -->
<A HREF="/">Home</A>
<!-- Good -->
<a href="/">Home</a>
For the sake of consistent rendering within browsers, always specify HTML5 DOCTYPE at the top of the code. XHTML is not recommended because it lacks browser support as well as tool support, and it no longer fits the standards of modern browsers.
<!DOCTYPE html>
<html>
<head>
</head>
</html>
Define the document’s language by giving it a lang
attribute to the outer most <html>
tag. Screen Readers use the lang
attributes to detect the documents’ languages and transform text into audio or provide appropriate pronunciations.
Note HTML5 Element further explains the lang attribute. List of language codes
<html lang="ko">
<!-- ... -->
</html>
Internet Explorer uses meta tags to make sure that the page is rendered correctly given a specific version. To prevent IE from rendering differently, use the latest Edge
mode.
Note To learn more about IE Compatibility, refer to this stack overflow article.
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
If a metatag charset
is used to specify the character encoding scheme, browsers and development tools detect the document’s encoding faster and more accurately. Character encoding is based on Unicode, and it is recommended to use the most widely used UTF-8 because of its excellent backwards compatibility.
Note To learn more about encoding schemes used for HTML and CSS, refer to W3C Tutorial.
<html lang="ko">
<meta charset="UTF-8">
</head>
Do not explicitly specify the values of Boolean attributes like selected
, disabled
, and checked
.
<!-- Bad -->
<input type="text" disabled=true>
<!-- Good -->
<input type="text" disabled>
<!-- Good -->
<input type="checkbox" value="1" checked>
<!-- Bad -->
<input type="checkbox" value="1" checked=true>
<!-- Good -->
<select>
<option value="1" selected>1</option>
</select>
<!-- Bad -->
<select>
<option value="1" selected=true>1</option>
</select>
If at all possible, avoid using unnecessary tags. The size of the HTML document directly correlates with the amount of data transferred over the network. The depth of the HTML document affects the weight of the render tree browsers use to render, so lighter files render faster. [FE Guide] Performance Guide explains the rendering performance in greater detail.
<!-- Bad -->
<span class="tui">
<img src="...">
</span>
<!-- Good -->
<img class="tui" src="...">
Use HTML tags with purpose. For example, only use <h>
tag to represent a header, use <p>
tag to represent a paragraph, and use <a>
tag to represent a hyperlink. Also, using new semantic tags introduced in HTML5 like <header>
, <nav>
, and <article>
benefits accessibility, reusability, and Search Engine Optimization (SEO).
<!-- Bad -->
<p><strong>All recommendations</strong></p>
<!-- Good -->
<h3>All recommendations</h3>
<!-- Bad -->
Some text
<br />
<br />
Some more text
<!-- Good -->
<p>Some text</p>
<p>Some more text</p>
<!-- Bad -->
<div onclick="bad();">go</div>
<!-- Good -->
<a href="good/">go</a>
Do not use entity references. If the document follows the same encoding scheme appropriately, every character appears as typed, so entity references like —
,”
, and ☺
are unnecessary. However, reserved characters in HTML like <
or &
require entity references.
<!-- Bad -->
The currency symbol for the Euro is `“&eur;”`.
<!-- Good -->
The currency symbol for the Euro is “€”.
According to the specifications of HTML5, the file type
attributes are already set as text/css
and text/javascript
when using external files, so it is unnecessary to specify them with attribute values.
Note HTML5 Specifications Style HTML5 Specifications Script HTML5 Specifications
<!-- Bad -->
<link rel="stylesheet" href="//uicdn.toast.com/tui.chart/latest/tui-chart.min.css" type="text/css">
<!-- Good -->
<link rel="stylesheet" href="//uicdn.toast.com/tui.chart/latest/tui-chart.min.css">
<!-- Bad -->
<script src="//uicdn.toast.com/tui.chart/latest/tui-chart.min.js" type="text/javascript"></script>
<!-- Good -->
<script src="//uicdn.toast.com/tui.chart/latest/tui-chart.min.js"></script>
When JavaScript is included in the <head>
, the page rendering is postponed until all of the JavaScript files have finished downloading, parsing, and compiling, so it is better to include it at the bottom of the body. (Related file: [FE Guide] Include the script file at the bottom of the document.
<!-- Bad -->
<!DOCTYPE html>
<html>
<head>
<title>HTML Page</title>
<link rel="stylesheet" href="//uicdn.toast.com/tui.chart/latest/tui-chart.min.css" type="text/css">
<script src="//uicdn.toast.com/tui.chart/latest/tui-chart.min.js"></script>
</head>
...
</html>
<!-- Good -->
<!DOCTYPE html>
<html>
<head>
<title>HTML Page</title>
<link rel="stylesheet" href="//uicdn.toast.com/tui.chart/latest/tui-chart.min.css" type="text/css">
</head>
<body>
...
<!-- Included at the end of the body tag-->
<script src="//uicdn.toast.com/tui.chart/latest/tui-chart.min.js"></script>
</body>
</html>
Use two empty spaces
to indent. Instead of using camelCase and snake_case, kebab-case is used to name classes and ids. For the sake of readability, use a single space
before the opening declarative curly bracket ({
) and place the ending curly bracket (}
) on a separate line.
/* Bad */
.firstSelector {}
#buttonId {}
#button-id{
...}
/* Good */
.first-selector {}
#button-id {
...
}
At the point of declaration, add a single space after a colon :
.
/* Bad */
.selector {
padding:15px;
margin : 15px;
}
/* Good */
.selector {
padding: 15px;
margin: 15px;
}
To describe a single attribute, use one line. Contrarily, use one line per attribute to describe multi attributed properties.
/* Bad */
.selector {
padding:15px;
}
.selector {padding: 15px;margin: 15px;}
/* Good */
.selector {padding:15px;}
.selector {
padding: 15px;
margin: 15px;
}
When referencing multiple selectors, list them out in one line.
/* Bad */
.selector, .selector-secondary, .selector[type=text] {
...
}
/* Good */
.selector,
.selector-secondary,
.selector[type="text"] {
...
}
At the end of every style statement, use a semicolon. Although the semicolon is optional for the last statement, leaving it out makes the file more susceptible to errors.
/* Bad */
.selector {
color: blue;
margin: 20px;
padding:15px
}
/* Good */
.selector {
color: blue;
margin: 20px;
padding: 15px;
}
Always use classes to set styles. Ids have zero reusability, but have infinitely high specificity. Such characteristics could lead to unpredictable behaviors. Only use ids in special cases like link management and for
statements.
Note To learn more about specificity, refer to this article on CSS Wizardry.
When using JavaScript to register an event handler to the DOM, do not use classes designed to set styles. CSS style statements and JavaScript action control have different responsibilities, so managing them separately makes maintenance easier. In this case, attaching a js-
prefix in front of classes used for JavaScript is recommended.
<button class="btn js-submit">submit</button>
/* Bad */
margin: 1px 0px 2px 0px;
padding: 0px;
/* Good */
margin: 1px 0 2px 0;
padding: 0;
flex: 0px; // For flex-basis component, unit of measurement is required.
If there is no border, use 0
instead of none
.
/* Bad */
.no-border {border: none;}
/* Good */
.no-border {border: 0;}
When using hexadecimals to represent colors, use three characters, as shown in the example below, if possible.
/* Bad */
color: #eebbcc;
/* Good */
color: #ebc;
In order to maintain high rendering performance, if at all possible, use class selectors instead of tag selectors.
/* Bad */
span { ... }
While it is possible to use tag selectors with attribute selectors (eg>[class^="..."]
), using the two together causes performance issues, so should be avoided. To use the type
selector, use double quotation marks. (eg>input[type="text"]
)
/* Bad */
span[class^="main"] { ... }
/* Good */
.main { ... }
Note Fore more examples dealing with type selectors, refer to this document.
Limit the selector length to maximum of three, and try to keep it as short as possible. Parent selector should be included only if it must be
included.
/* Bad */
.page-container #stream .stream-item .tweet .tweet-header .username { ... }
/* Good */
.tweet-header .username { ... }
For properties like padding
, margin
, font
, background
, border
, and border-radius
, use abbreviations if possible.
/* Bad */
font-family: 'Open Sans', 'Noto Serif ', sans-serif;
font-size: 100%;
line-height: 1.6;
padding-bottom: 2px;
padding-left: 1px;
padding-right: 1px;
padding-top: 0;
/* Good */
font: 100%/1.6 'Open Sans', 'Noto Serif ', sans-serif;
padding: 0 1px 2px;
Abbreviating should not rampage overboard.
/* Bad */
.element {
margin: 0 0 10px 0;
background: #c83636;
background: url("back.jpg");
}
/* Good */
.element {
margin-bottom: 10px;
background-color: #c83636;
background-image: url("back.jpg");
}
<link>
instead of @import
.Compared to <link>
, @import
takes too long; therefore, it should not be used. If an @import
is used within the <link>
, the browser cannot process the CSS while the @import
ed materials are downloading, so the loading time increases dramatically. Also, if an error occurs during the download sequence, such errors are incredibly hard to detect.
<!-- Bad -->
<style>
@import url("more.css");
</style>
<!-- Good -->
<link rel="stylesheet" href="core.css">
Note To see more detailed experiment results regarding import, refer to an article by Steve Souders.
Instead of using .sass
syntax based on indentation, use scss
syntax which is built to be compatible with every syntax and functionality in CSS.
/* .sass syntax */
.black-div
background: black
border: 1px solid #ccc
span
padding: 10px;
/* .scss syntax */
.black-div {
background: black;
border: 1px solid #ccc;
span {
padding: 10px;
}
}
The order of declaration is as follows: attribute, @include
, and nested selectors. After @include
, always insert a new line.
.black-div {
background: black;
border: 1px solid #ccc;
@include transition(background 0.5s ease)
.icon {
padding: 10px;
}
}
Instead of camelCase or snakecase, use kebab-case that uses a dash -
to name variables. If the file is local, it is possible to use it with an underscore (``).
/* Bad */
$mainColor: blue;
$main_color: blue;
/* Good */
$main-color: blue;
Mixin should be used like a function to distinguish repetitive styles or abstract complex codes. Especially, mixins without inputs can result in codes that are unnecessary without compression process like Gzip, so it warrants extra caution.
@mixin button($color) {
background-color: $color;
border-radius: 5px;
padding: .25em .5em;
&:hover {
cursor: pointer;
background-color: $color;
border-color: $color;
}
}
.button-a {
@include button(#b4d455);
}
.button-b {
@include button(#c0ffee);
}
The same can be done with the code below.
.button-a {
background-color: #b4d455;
border-radius: 5px;
padding: .25em .5em;
}
.button-a:hover {
cursor: pointer;
background-color: #b4d455;
border-color: #b4d455;
}
.button-b {
background-color: #c0ffee;
border-radius: 5px;
padding: .25em .5em;
}
.button-b:hover {
cursor: pointer;
background-color: #c0ffee;
border-color: #c0ffee;
}
@extend
s are not used because they are not intuitive and could cause problems when used with nested selectors. Using Gzip with Mixin produces the same benefits of @extend
without the risks.
After the third level, it is possible that the codes are too intricately involved with the HTML or that the codes are not reusable.
.wrapper {
.container {
.content {
...
}
}
}
Static Analysis Tools enable automation of tests to check for coding convention and proceeds to inspect possible erroneous patterns and basic structures. It is being widely adopted because of the fact that it punctually gives feedback synchronized with development tools. Also, it is easily customizable with easy addition and deletion of rules.
Stylelint, as one of widely used CSS lint tools, supports up-to-date CSS syntax and allows easy addition of new rules. The following section will demonstrate the installing process and basic commands over the command line interface (CLI).
Stylelint can be installed easily using the npm.
$ npm install –save-dev stylelint stylelint-config-recommended
Stylelint can be executed by adding to the package.json
and using the npm commands.
"scripts": {
"stylelint": "stylelint style.css"
}
Options can be applied using .stylelintrc
, stylelint.config.js
, or package.json
, and explanations regarding available rules can be found on the official user guide. It can also be used like ESLint, by only using predefined settings and applying only the extended version of desired rules.
stylelint-config-recommend
: This is an extension module recommended by stylelint that contains possible errors. Additionally, this extension can be modified to suit personal needs and create a custom setting. If Prettier is installed, it is recommended to use stylelint-config-recommended
. stylelint-config-recommended
and adding a new rule that only allows px as a unit of measurement. module.exports = {
"extends": "stylelint-config-recommended",
"rules": {
"unit-whitelist": ["px"]
}
}
// style.css
p {
border: 1em solid #ccc;
}
When the file is ran on CLI by typing $ npm run stylelint
, it raises a Unexpected unit "em"
.
This document was written to serve as an introduction to HTML, CSS, and Sass. This guide is based on the basic style rules used in FE Development Lab, and is subjected to change depending on the supporting browser, device, and frameworks. It is the hope of the author that this guide helps developers write consistent codes, cooperate easily with other developers, and minimize maintenance and expansion cost.
This document is an official Web Front-End development guide written and maintained by NHN Cloud FE Development Lab. Any errors, questions, and points of improvement pertaining to this document should be addressed to the official support channel (dl_javascript@nhn.com).
Last Modified |
---|
2019. 03. 29 |