There’s a lot of obsolete information about HTML and CSS and how to do websites, many are outdated, whereas other more current are either too deep into technicalities or just in need to be found.
Using the thme “the right way” this site is an open-source reference which follows the “fork”, “pull request” contribution model popular on GitHub.
This site is a user-contributed (and reviewed) documentation describing web development best-practices, based on two goals:
The target audience is people who wants to learn (or re-learn) with today’s HTML+CSS+Javascript best practices to build a web that is future proof.
Sites that follows the “fork me” on github concept documenting best practices for web development:
The site barely started, it is a direct action triggered by Move the web Forward, contribute section with proposed requests ”Lazyweb requests” asking for tools and solutions that would be cool to have for web developers issue #73
This is a living document and will continue to be updated with more helpful information and examples as they become available.
Help make this website the best resource for new Frontend developers! Contribute on GitHub, Ask how is the best way to (…)
Use shorthand CSS techniques, when saving those extra bytes is crucial for you!
Usage of shorthand or longhand are not only for brievety purposes. One common use case is to define in full the desired style using short hand, then, override specific style using longhand.
In most condition, the ideal premise is to see all element as a module and extend variants.
To illustrate this, imagine you want a type of block to set text content in. Content can be (only) a blog post introduction text, a code-snippet, a picture.
Let’s nicknamme it ”marble
” (as for the example), each of them needs different styling but some of it has common styling effects.
/* a contrasting color to the background slate */
.marble {
border:1px solid white;
padding:25px;
background:url(marble.png) #FFF repeat;
}
The previous could be a base module to use. Further down the project you could have “theme” section that takes care of the project specific theme.
/* in the project theme, override only what is specific to the project's theme */
.marble {
background-color: #FCFCFC;
border-color: #FCFCFC;
border-radius: 5px; /* And add this border radius too, please! */
}
Imagine all content area are marble
and some other will have a clear different style, imagine now we need to style a source-code block, just fork a different behavior to it.
/* use: <div class="marble marble-code">Hello world</div> */
.marble-code {
font-family: sans-serif;
}
Beware of the cascading effect. If you set a specific effect, make sure there is not already defined. Being precise becomes more and more important as the code stacks up.
/* longhand */
padding-top:5px;
padding-right:5px;
padding-bottom:5px;
padding-left:5px;
/* shorthand */
padding:5px;
/* longhand */
padding-top:1px;
padding-right:2px;
padding-bottom:1px;
padding-left:2px;
/* shorthand */
padding:1px 2px;
/* longhand */
padding-top:1px;
padding-right:2px;
padding-bottom:3px;
padding-left:2px;
/* shorthand */
padding:1px 2px 3px;
/* longhand */
padding-top:1px;
padding-right:2px;
padding-bottom:3px;
padding-left:4px;
/* shorthand */
padding:1px 2px 3px 4px;
/* longhand */
margin-top:5px;
margin-right:5px;
margin-bottom:5px;
margin-left:5px;
/* shorthand */
margin:5px;
/* longhand */
margin-top:1px;
margin-right:2px;
margin-bottom:1px;
margin-left:2px;
/* shorthand */
margin:1px 2px;
/* longhand */
margin-top:1px;
margin-right:2px;
margin-bottom:3px;
margin-left:2px;
/* shorthand */
margin:1px 2px 3px;
/* longhand */
margin-top:1px;
margin-right:2px;
margin-bottom:1px;
margin-left:2px;
/* shorthand */
margin:1px 2px;
/* longhand */
border-width:1px;
border-style:solid;
border-color:#000;
/* shorthand */
border:1px solid #000;
/* longhand */
border-top-width:1px;
border-right-width:2px;
border-bottom-width:3px;
border-left-width:4px;
/* shorthand */
border-width:1px 2px 3px 4px;
A common caveat about fonts is that, like colors, their effect bubbles up until it is redefined in a stronger selector.
Beware of the original definition then, when needed, use the most precise longhand to do your effect.
Sometimes it is even better to create a specific sub class (e.g. bolded
) than being over specific (e.g. header > nav strong.title {}
, albeit specific, is considered as a VERY BAD practices)
/* longhand */
font-style:italic;
font-variant:small-caps;
font-weight:bold;
font-size:1em;
line-height:140%;
font-family:"Lucida Grande",sans-serif;
/* shorthand */
font:italic small-caps bold 1em/140% "Lucida Grande",sans-serif;
/* longhand */
background-color:#f00;
background-image:url(background.gif);
background-repeat:no-repeat;
background-attachment:fixed;
background-position:0 0;
/* shorthand */
background:#f00 url(background.gif) no-repeat fixed 0 0;
/* longhand */
color:#000000;
color:#336699;
color:#0099CC;
/* shorthand */
color:#000;
color:#369;
color:#09C;
/* longhand */
list-style-type:square;
list-style-position:inside;
list-style-image:url(image.gif);
/* shorthand */
list-style:square inside url(image.gif);
/* longhand */
outline-color:#f00;
outline-style:solid;
outline-width:2px;
/* shorthand */
outline:#f00 solid 2px;
Extending or re-using one (or many) front-end libraries is a very common practice. The holy-grail of efficiency in front-end development practices is to be able to import re-usable libraries and adapt to the project’s requirements.
For example. Imagine you want to create a new project, and you already have a few modules available e.g. alert or notification message that could be used in any other projects.
This tutorial is about isolating your own project-specific code, get the benefit of already made patterns that can then mixed-matched for every specific views you may need.
Unfortunately, a common mistake is that people simply copy-paste code from project to project without real version scheme or version control mechanisms at all (e.g. Git, Subversion). From a set of personnal, mixed with some other project’s source.
Carrying practices and “dead-wood” code alone every project, without follow up from the author or the source.
Although source-control is suggested, the essential to remember is to not modify external libraries. But merely extend and adapt; this is where CSS parsers comes in handy (more on this later).
A better would be to use the same concepts that programmers uses in the Object Oriented paradigm. In a few words:
Import, extend your specialized version, separate concerns, re-use. profit.
This is roughly what OOCSS (Object Oriented CSS) stands for.
But why re-inventing when you can just use and reuse existing in an efficient way?
To be able to re-use, and separate concerns, we have no choice, we need something to process and replace things around.
You may follow my drift if you ever had wishes similar to those:
background-color:#000000 /* THEME: color #595958 plus 100% darker */
color: darken($themeColor, 10%);
existedThis is some of my own personal reasons I prefer using compiled CSS.
After that, there is a lot of CSS parsers.
Personally, I like LESS. Because: it can run in the browser, on the server side (within NodeJS), compile from the command line, and be used in automated deployment tools.
A killer argument is that it can only as simple as.
<link rel="stylesheet/less" type="text/css" href="styles.less" />
<script src="less.js" type="text/javascript"></script>
To use in production, get the compiled CSS in the localStorage
from Firefox/Chrome (in the developer tools such as Firebug) the compiled css and commit the css to the project’s as minified CSS.
Not to forget that you can also use as much as you need @include
statements and separate your code, but end up with ONE css file.
Create a folder within your project that will handle external libraries.
(rest of your project tree)
web/
assets/
lib/
bootstrap/
misc/
js/
myproject/
_variables.less
_adaptations.less
_modules.less
_states.less
_fonts.less
main.less
In the web/assets/lib/bootstrap/
either download, svn external or submodule from a specific version and keep it as it is. untouched.
While in this example I use Bootstrap, I often use some specific sup-parts from the also Excellent Zurb Foundation, their font-icons, library for example.
Then. In main.less
(or any name you choose as your “main”); copy-paste the content from the original web/assets/lib/bootstrap/less/bootstrap.less
into web/assets/main.less
, and adjust paths accordingly.
Now that you have this basic workspace, have a look at Bootstrap’s variables.less
file, see myproject/_variables.less
has my own version of the original.
Beware though. To avoid compilation errors; just make sure to include the original variables.less
file, and only override what you need.
The rest comes by creating patterns and separate concerns.
For example, Imagine you have the module .form-actions
and you need to adjust for your needs.
We have the original:
.navbar-fixed-top {
position: fixed;
top: 0;
right: 0;
left: 0;
z-index: @zindexFixedNavbar;
}
.navbar-fixed-top .navbar-inner {
padding-left: 0;
padding-right: 0;
.border-radius(0);
}
Then, in your own project code (e.g. in _adaptations.less
), you could adjust the original with specific styling:
.myproject > .navbar-fixed-top .divider-vertical {
background-color: lighten(@themeDarkestColor, 6%);
border-right-color: darken(@themeDarkestColor, 15%);
height: 62px;
}
See also that I did not overspecify but precisely wanted to be the direct children (>
) of .myproject
that, in this case, is assigned to the <body>
tag.
The key for re-use is to separate the concerns and not edit your external libraries. By doing so, you will learn how to be very specific with shorthand and selectors, without creating ridiculous selector trails.
I thought to re-visit the previous post because somebody asked on the Bootstrap Mailing list if they can change some elements colors using plain css.
I was assuming that the person do not know the existence of css pre-processors so I shared the following blueprint on how to do.
It is a bad practice to modify external library but better extending it. Here’s how
Create a copy of bootstrap.less outside of bootstrap distribution folder.
Adjust path on the bootstrap.less @include directives.
Create your own variables.less
Call that one in your own new bootstrap.less file
The new variables.less file should have only variables you want to rewrite. And it should have an include at its top to the original (aka overloading) variables.less file
Follow LESS css pre-processor howto to use less and yoi can change colours!
Best regards
During web development, it often happens you want to attach events handler on something in your page. A common usage could be you want to flip a plus sign to a minus sign when you click on a button.
<a href="/some/url/324" class="flip-icon" data-target="#generated-324"><i class="icon-plus"></i></a>
Later in a script you may be compelled to do something similar to the following (assuming you are using jQuery):
$(document).ready(function(){
// Rest of the document in document.ready
// DO NOT USE AS-IS, SEE LAST EXAMPLE
$('.flip-icon.).click(function(event){
event.preventDefault();
var clicked = $(this);
var flipElement = clicked.find('i');
if (flipElement.hasClass('icon-plus')) {
flipElement.removeClass('icon-plus').addClass('icon-minus');
} else {
flipElement.removeClass('icon-minus').addClass('icon-plus');
}
});
});
But what happens if you want to add other events such as, for example, activating an accordion. You may end up with duplicating events and get some collisions.
Did you know that the ‘click’ event is only a string and you can create any event name you may want?
To describe what I am refering to, I have a add an other behavior that will also, in part, require the previous example.
Imagine we have an accordion managed already grabbing the element’s a[data-target]
click event handler.
$(document).ready(function(){
// Rest of the document in document.ready
// DO NOT USE AS-IS, SEE LAST EXAMPLE
$('a[data-target]').click(function(event){
// do the accordion stuff
});
});
But, what if for some reason, our page has to reload some sections and our event handler managing the a[data-target]
click gets lost
Instead, of creating a click specific event handler (what if we want to change) and be potentially lost with the element to attach event onto.
You can use jQuery’s on
method and attach an event to the <body>
, a safe element that every document has.
Things to note about the on
method:
Function
object to handle the eventAlso, there is nice thing about bubbling.
When an event happens, the event crawls the DOM up to the body (called ‘catch’) then gets back to the triggerer element (called ‘bubbling’) and firing in that order all event handlers.
Knowing all of this now, instead of attaching a single event type handler to a specific element, let’s take advantage of our new knowledge.
'use strict';
$(document).ready(function(){
// Rest of your document
// Look at the 'flip-my-icon-event', we just made-up that one. See below.
$('body').on('click flip-my-icon-event', '.flip-icon', function(){
/* Look here ************************* */
// Let's put it also in a self-executing anonymous, to isolate scope
(function(triggered){
// Same as earlier.
var clicked = $(this);
var flipElement = clicked.find('i');
if (flipElement.hasClass('icon-plus')) {
flipElement.removeClass('icon-plus').addClass('icon-minus');
} else {
flipElement.removeClass('icon-minus').addClass('icon-plus');
}
// End same as earlier
})($(this)); // this fires the self-executing.
});
$('body').on('click', 'a[data-target]', function(event){
event.preventDefault();
// do the accordion stuff
var collapsible = $($(this).attr('data-target'));
if (typeof collapsible.attr('data-collapsible') === 'undefined') {
collapsible
.collapse()
.attr('data-collapsible', 'applied')
.on('show', function(){
jQuery(this).parent().removeClass('is-hidden');
})
.on('hide', function(){
jQuery(this).parent().addClass('is-hidden');
});
// End do the accordion stuff
jQuery(this).trigger('click').trigger('flip-my-icon-event');
/* Look here ******************************* */
}
});
});
The following works, because of the following trigger html pattern, as from the begining:
<a href="/some/url/324" class="flip-icon" data-target="#generated-324"><i class="icon-plus"></i></a>
And of the following:
.icon-plus
and .icon-minus
class namesa[data-target]
attribute has ALSO a .flip-icon
class namea[data-target]
triggers our made-up flip-my-icon-event
event to an element that also matches (see the two ‘look here’ comments)References
trigger
method from the jQuery sourceon
method from the jQuery sourceon
methodlive
, or delegate
are considered deprecated (as of jQuery 1.7) see delegate API and live API notes.