/* TODO: Summarize the best practices for CSS with visual examples */
- There is an option to
reset
ornormalize
the CSS. Read about the differences. here and here - reset.css by Eric Meyer
- normalize.css by Necolas
Tl;dr: CSS resets aim to remove all built-in browser styling. Normalize CSS aims to make built-in browser styling consistent across browsers.
- The How and Why of Clearing Floats
- All About Floats
- Use the Micro Clearfix to clear floats.
- Instead of
spans
, use thei
elements for icons. It makes it easier to identify the icons location on the page. Still using sprite images instead of SVG icons? Try using FontCustom - it helps generate the complete.css
andSVG fonts
for your project. You just need to provide the SVG icons templates.
<p><i class="icon icon-comment"></i>23 comments</p>
...
.icon { background-image: url( sprites.png ); }
.icon-comments { background-position: 0 -30px; }
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
// images doesn't work well with border-box
// they still got resized after adding borders
img {
box-sizing: content-box;
}
Example a dropdown list.
<div class='dropdown dropdown-list'>
<div class='list'>
<div class='list-image'></div>
<div class='list-detail'></div>
</div>
</div>
/* structure the css based on the html structure
* add indentation if the html is nested
**/
.dropdown {}
.dropdown-list{}
.list {}
.list-image {}
.list-detail {}
Problem: Designing a proper css layout can be cumbersome. Solution:
- Separate views and components
- Separate views for presentation (static, dynamic rendering) and views for actions (button)
- Views for
presentation
should use BEM naming pattern - Views for
actions
should use js-hook naming pattern - Use rows and colums naming for designing layouts
- Layout determine the structure of the page, design it well.
- Layout might change according to the screen size.
- Some common layout is the Header-Footer-Layout.
Always ensure that there is a View (a.k.a container or box) that holds a component. It is easier to compose the layout this way. Another benefit is that rendering on the JavaScript side is simpler - just render the ShareComponent into the ShareView (else you might resort to append the view, which will affects the layout composition).
<div id=ShareView>
<div id=ShareComponent class=share>
<div class=share-link>Facebook</div>
<div class=share-link>Google+</div>
<div class=share-link>Twitter</div>
</div>
</div>
To ensure that all UI designs fit nicely on the mobile, follow the @320px principle
. All UI design (components) should be resizable to 320px, and still retain it's functionality.
If there are multiple similar components on the same page (e.g. modal popup), the naming can be repetitive:
<!--BAD: does not share the same component classes-->
<div class="modal-report">...</div>
<div class="modal-alert">...</div>
<div class="modal-confirm">...</div>
<div class="modal-confirm-delete">...</div>
<div class="modal-confirm-update">...</div>
<!--OK: with BEM modifiers-->
<div class="modal-popup modal--alert">...</div>
<div class="modal-popup modal--confirm">...</div>
<!--OK: with data-attributes-->
<div class="modal-popup" data-role="alert">...</div>
<div class="modal-popup" data-role="confirm">...</div>
<!--OK: with id (but not suitable for lists)-->
<div class="modal-popup" id="modalAlert">...</div>
<div class="modal-popup" id="modalConfirm">...</div>
There are three modal confirms markup in the html body. This is bad. One way is to create a single dynamic modal - one whose content can be replaced with a template. That way, we can keep the code DRY. Another possibility is to create one single component in which you can pass in template as options:
var modalAlert = new ModalPopup({
template: "<div>This is an alert!</div>", // string template for content
btnConfirm: "OK", // set the text to "OK"
btnCancel: null // will not show the button
});
var modalForm = new ModalPopup({
template: "<div class='report-view'><form>...some form here</form></div>",
btnConfirm: "SUBMIT",
btnCancel: "Cancel",
onConfirm: function () {
// do something once the user clicks the confirm button
},
onCancel: function () {
// do something once the user clicks the cancel button
}
});
Each components should be placed in View
. The View
is synonymous to Box
or Container
. The purpose of the View
is for managing the positioning of the components. Since the properties for the components are shared through their classes, it is best not to include positional properties in the component's class. The structure is as follow:
main > layout > view > components
Typography should be designed to be responsive. Do not use rem
or em
to set the responsive fonts - it is not a good idea to scale the font-size linearly. Small fonts will be illegible that way. Instead you can adapt the following pattern:
/* .{font-weight}-{font-size}-{color} */
.medium-36px-silver {
font-weight: medium;
font-size: 36px;
color: #999;
}
/* another alternative, but probably inefficient */
[class*="medium"] {
font-weight: medium;
}
[class*="36px"] {
font-size: 36px;
}
[class*="silver"] {
color: #999;
}
@media (max-width: 720px) {
/* targets all classes that contains the keyword `36px` */
[class*="36px"] {
font-size: 20px;
}
}
Do not mix horizontal (left and right) padding/margin with vertical (spacing/break) padding/margin.
.br {
height: 20px; /* default */
display: block;
width: 100%;
}
/* When debugging, just use jquery to select all the .br elements and append the class is debugging. */
.br--20.is-debugging {
background: rgba(255, 0, 0, 0.5);
}
.br--10.is-debugging {
background: rgba(0, 255, 0, 0.5);
}
- section
- padding/margin
- responsive
- media-query
- font-size
- For horizontal spacing, use a custom
<Break height={10}/>
component that accepts a height props. - For left/right padding, use css to customize
- If we have multiple columns in a row, use CSS-grid to separate them, rather than using a div with a fix width, or spaces.
- Avoid having borders in a component, this complicates thing when we need to add padding to them. Set the border at the parent component instead.
Create a base font without height and width, but just inherits the font family. Create custom fonts headings from this base font to reuse them.
Use css variables for the colors/margin. But if you need them programmatically in JS, you might want to create another file to store these values. This really depends on your use case - if you are exporting them to be used as a package, you might want to make the colors available for both css and js.