Like any coding standard, the purpose of the WordPress CSS Coding Standards is to create a baseline for collaboration and review within various aspects of the WordPress open source project and community, from core code to themes to plugins. Files within a project should appear as though created by a single entity. Above all else, create code that is readable, meaningful, consistent, and beautiful.
Within core stylesheets, inconsistencies will often be found. We are working on addressing these and make every effort to have patches and commits from this point forward follow the CSS coding standards. More information on the above and contributing to UI/front-end development will be forthcoming in a separate set of guidelines.
Structure
There are plenty of different methods for structuring a stylesheet. With the CSS in core, it is important to retain a high degree of legibility. This enables subsequent contributors to have a clear understanding of the flow of the document.
- Use tabs, not spaces, to indent each property.
- Add two blank lines between sections and one blank line between blocks in a section.
- Each selector should be on its own line, ending in either a comma or an opening curly brace. Property-value pairs should be on their own line, with one tab of indentation and an ending semicolon. The closing brace should be flush left, using the same level of indentation as the opening selector.
Correct:
#selector-1,
#selector-2,
#selector-3 {
background: #fff;
color: #000;
}
Incorrect:
#selector-1, #selector-2, #selector-3 {
background: #fff;
color: #000;
}
#selector-1 { background: #fff; color: #000; }
Selectors
With specificity, comes great responsibility. Broad selectors allow us to be efficient, yet can have adverse consequences if not tested. Location-specific selectors can save us time, but will quickly lead to a cluttered stylesheet. Exercise your best judgement to create selectors that find the right balance between contributing to the overall style and layout of the DOM.
- Similar to the WordPress Coding Standards for file names, use lowercase and separate words with hyphens when naming selectors. Avoid camelcase and underscores.
- Use human readable selectors that describe what element(s) they style.
- Attribute selectors should use double quotes around values
- Refrain from using over-qualified selectors,
div.container can simply be stated as .container
Correct:
#comment-form {
margin: 1em 0;
}
input[type="text"] {
line-height: 1.1;
}
Incorrect:
#commentForm { /* Avoid camelcase. */
margin: 0;
}
#comment_form { /* Avoid underscores. */
margin: 0;
}
div#comment_form { /* Avoid over-qualification. */
margin: 0;
}
#c1-xr { /* What is a c1-xr?! Use a better name. */
margin: 0;
}
input[type=text] { /* Should be [type="text"] */
line-height: 110% /* Also doubly incorrect */
}
Properties
Similar to selectors, properties that are too specific will hinder the flexibility of the design. Less is more. Make sure you are not repeating styling or introducing fixed dimensions (when a fluid solution is more acceptable).
- Properties should be followed by a colon and a space.
- All properties and values should be lowercase, except for font names and vendor-specific properties.
- Use hex code for colors, or rgba() if opacity is needed. Avoid RGB format and uppercase, and shorten values when possible: #fff instead of #FFFFFF.
- Use shorthand (except when overriding styles) for background, border, font, list-style, margin, and padding values as much as possible. (For a shorthand reference, see CSS Shorthand.)
Property Ordering
“Group like properties together, especially if you have a lot of them.”
– Nacin
Above all else, choose something that is meaningful to you and semantic in some way. Random ordering is chaos, not poetry. In WordPress Core, our choice is logical or grouped ordering, wherein properties are grouped by meaning and ordered specifically within those groups. The properties within groups are also strategically ordered to create transitions between sections, such as background directly before color. The baseline for ordering is:
- Display
- Positioning
- Box model
- Colors and Typography
- Other
Things that are not yet used in core itself, such as CSS3 animations, may not have a prescribed place above but likely would fit into one of the above in a logical manner. Just as CSS is evolving, so our standards will evolve with it.
Top/Right/Bottom/Left (TRBL/trouble) should be the order for any relevant properties (e.g. margin), much as the order goes in values. Corner specifiers (e.g. border-radius-*-*) should be top-left, top-right, bottom-right, bottom-left. This is derived from how shorthand values would be ordered.
Another method that is often used, including by the Automattic/WordPress.com Themes Team, is to order properties alphabetically, with or without certain exceptions.
Example:
#overlay {
position: absolute;
z-index: 1;
padding: 10px;
background: #fff;
color: #777;
}
Vendor Prefixes
Vendor prefixes should go longest (-webkit-) to shortest (unprefixed). Values should be right aligned with spaces after the colon provided that all the values are the same across all prefixes.
Preferred method:
.koop-shiny {
-webkit-box-shadow: inset 0 0 1px 1px #eee;
-moz-box-shadow: inset 0 0 1px 1px #eee;
box-shadow: inset 0 0 1px 1px #eee;
-webkit-transition: border-color 0.1s;
-moz-transition: border-color 0.1s;
-ms-transition: border-color 0.1s;
-o-transition: border-color 0.1s;
transition: border-color 0.1s;
}
Not preferred:
.okay {
-webkit-box-shadow: inset 0 0 1px 1px #eee;
-moz-box-shadow: inset 0 0 1px 1px #eee;
box-shadow: inset 0 0 1px 1px #eee;
}
.bad {
-webkit-box-shadow: inset 0 0 1px 1px #eee;
-moz-box-shadow: inset 0 0 1px 1px #eee;
box-shadow: inset 0 0 1px 1px #eee;
}
Special case for CSS gradients:
.gradient {
background: #fff;
background-image: -webkit-gradient(linear, left bottom, left top, from(#fff), to(#000));
background-image: -webkit-linear-gradient(bottom, #fff, #000);
background-image: -moz-linear-gradient(bottom, #fff, #000);
background-image: -o-linear-gradient(bottom, #fff, #000);
background-image: linear-gradient(to top, #fff, #000);
}
Values
There are numerous ways to input values for properties. Follow the guidelines below to help us retain a high degree of consistency.
- Space before the value, after the colon
- Do not pad parentheses with spaces
- Always end in a semicolon
- Use double quotes rather than single quotes, and only when needed, such as when a font name has a space.
- 0 values should not have units unless necessary, such as with transition-duration.
- Line height should also be unit-less, unless necessary to be defined as a specific pixel value. This is more than just a style convention, but is worth mentioning here. More information: http://meyerweb.com/eric/thoughts/2006/02/08/unitless-line-heights/
- Use a leading zero for decimal values, including in rgba().
- Multiple comma-separated values for one property should be separated by either a space or a newline, including within rgba(). Newlines should be used for lengthier multi-part values such as those for shorthand properties like box-shadow and text-shadow. Each subsequent value after the first should then be on a new line, indented to the same level as the selector and then spaced over to left-align with the previous value.
Correct:
.class { /* Correct usage of quotes */
background-image: url(images/bg.png);
font-family: "Helvetica Neue", sans-serif;
}
.class { /* Correct usage of zero values */
font-family: Georgia, serif;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.5),
0 1px 0 #fff;
}
Incorrect:
.class { /* Avoid missing space and semicolon */
background:#fff
}
.class { /* Avoid adding a unit on a zero value */
margin: 0px 0px 20px 0px;
}
Media Queries
Media queries allow us to gracefully degrade the DOM for different screen sizes. If you are adding any, be sure to test above and below the break-point you are targeting.
- It is generally advisable to keep media queries grouped by media at the bottom of the stylesheet.
- An exception is made for the wp-admin.css file in core, as it is very large and each section essentially represents a stylesheet of its own. Media queries are therefore added at the bottom of sections as applicable.
- Rule sets for media queries should be indented one level in.
Example:
@media all and (max-width: 699px) and (min-width: 520px) {
/* Your selectors */
}
Commenting
- Comment, and comment liberally. If there are concerns about file size, utilize minified files and the SCRIPT_DEBUG constant. Long comments should manually break the line length at 80 characters.
- A table of contents should be utilized for longer stylesheets, especially those that are highly sectioned. Using an index number (1.0, 1.1, 2.0, etc.) aids in searching and jumping to a location.
- Comments should be formatted much as PHPDoc is. The CSSDoc standard is not necessarily widely accepted or used but some aspects of it may be adopted over time. Section/subsection headers should have newlines before and after. Inline comments should not have empty newlines separating the comment from the item to which it relates.
For sections and subsections:
/**
* #.# Section title
*
* Description of section, whether or not it has media queries, etc.
*/
.selector {
float: left;
}
For inline:
/* This is a comment about this selector */
.another-selector {
position: absolute;
top: 0 !important; /* I should explain why this is so !important */
}
Best Practices
Stylesheets tend to get long in length. Focus slowly gets lost whilst intended goals start repeating and overlapping. Writing smart code from the outset helps us retain the overview whilst remaining flexible throughout change.
- If you are attempting to fix an issue, attempt to remove code before adding more.
- Magic Numbers are unlucky. These are numbers that are used as quick fixes on a one-off basis. Example:
.box { margin-top: 37px }.
- DOM will change over time, target the element you want to use as opposed to “finding it” through its parents. Example: Use
.highlight on the element as opposed to .highlight a (where the selector is on the parent)
- Know when to use the height property. It should be used when you are including outside elements (such as images). Otherwise use line-height for more flexibility.
- Do not restate default property & value combinations (for instance
display: block; on block-level elements).
Related Links
sourceforge 10:09 pm on April 8, 2013 Permalink | Log in to Reply
thank you, is this the html5 vid player? looks good, newer java based audio player is also needed, flash is always prone to attacks
Manny Fleurmond 10:11 pm on April 8, 2013 Permalink | Log in to Reply
How does this handle m4a files?
Samuel Wood (Otto) 11:24 pm on April 8, 2013 Permalink | Log in to Reply
Just fine. You’ll find that m4a is one of the supported audio extensions, and is supported by MediaElement.
Konstantin Obenland 10:59 pm on April 8, 2013 Permalink | Log in to Reply
The attentive reader might have noticed how the buffer- and play-time-bars in the first and second screenshot have different colors.
Themes can style these elements of the players. The first example is a screenshot from Twenty Thirteen, with a white buffer bar, an orange play time bar and no border-radius.
John Saddington 11:11 pm on April 8, 2013 Permalink | Log in to Reply
this is fantastic. john dyer’s MEJS is amazing.
AK Ted 11:32 pm on April 8, 2013 Permalink | Log in to Reply
This is great news! Can’t wait for stable to play with, no time atm for beta.
Small grammar correction: “ability to easily and beautifully expresses themselves” (in first paragraph), should be “express”.
Michael Beckwith 11:51 pm on April 8, 2013 Permalink | Log in to Reply
That’s pretty hot
Ipstenu (Mika Epstein) 1:07 am on April 9, 2013 Permalink | Log in to Reply
What’s the fallback? Like if I use
and they don’t allow for HTML5 (yes, I have people who don’t), what shows? Right now I made an html5video shortcode that has, at the bottom ‘Can’t see a video? Click here…’ and it defaults to the MP4.Scott Taylor 2:47 am on April 9, 2013 Permalink | Log in to Reply
I am pretty sure MP4 will win and play via Flash. If no flash and no HTML5, there will be a link that goes straight to the file.
Jon Brown 1:09 am on April 9, 2013 Permalink | Log in to Reply
Not sure how I missed this on trac, but “YAY!!! & Oh No!!!!”.
I just spent a month (not continuously) trying to figure out why MediaElements.js conflicted with Soliloquy (Flex based Slider) when both appeared on the same page on mobile. Only on mobile, everything worked fine everywhere else. I finally gave up, ditched ME.js for Video.js.
I’m now about to test that site on 3.6 just out of curiosity as to what happens.
I too really dislike this using shortcodes and my bigger concern is what this does to other plugins that use the shortcode already.
Always seemed to me WP ought to follow best naming practices and use [wp_gallery], [wp_video], etc…
Jon Brown 1:26 am on April 9, 2013 Permalink | Log in to Reply
That was easy to test… still conflicting somehow. I’ve let Thomas know with urls to dev/staging/live servers showing it all. It’s really bizzare that it only happens on mobile browsers (iOS chrome and safari) anbd throws no errors. Either works fine on it’s own, and we’ve recreated it on vanila WP running 2010.
Beau Lebens 1:42 am on April 9, 2013 Permalink | Log in to Reply
<3
Tomas 4:01 am on April 9, 2013 Permalink | Log in to Reply
WoW! This is good news!
Robert Chapin (miqrogroove) 1:48 pm on April 9, 2013 Permalink | Log in to Reply
That’s hot!
redwallhp 10:35 pm on April 9, 2013 Permalink | Log in to Reply
Awesome! The assimilation of the Crowd Favorite post format UI and MediaElement.js support in one version.
Eric Andrew Lewis 11:18 am on April 10, 2013 Permalink | Log in to Reply
Totally wow.
hearvox 12:22 am on April 11, 2013 Permalink | Log in to Reply
any hooks yet for skinning the default MEjs player?
Mark Jaquith 2:52 am on April 11, 2013 Permalink | Log in to Reply
See how Twenty Thirteen does it.
hearvox 4:53 am on April 11, 2013 Permalink | Log in to Reply
nice: looks like all elements of the player are CSS targetable via a slew of mejs-… classes.
rilwis 2:22 pm on April 11, 2013 Permalink | Log in to Reply
This feature is really great and useful for all people. I’ve been using MEjs and it’s really great. Nice UI, great support.
johndyer 10:48 pm on April 11, 2013 Permalink | Log in to Reply
So glad to hear it! Glad to have “contributed”
Maor Chasen 6:15 pm on April 12, 2013 Permalink | Log in to Reply
Love!
Anderton 9:06 am on April 15, 2013 Permalink | Log in to Reply
Have been playing around with it while developing a couple of themes for 3.6. It’s lovely, and easy to style. Have been using MediaElements,js before, and when i found out that it would be included in the Core, i was thrilled. Good move!
Bjarni Wark 10:25 pm on April 16, 2013 Permalink | Log in to Reply
Really good news, thanks for the efforts of making this happen.
Maeve Lander 4:58 am on April 17, 2013 Permalink | Log in to Reply
Just wondering how will this affect existing audio/video plugins? Any potential problems, conflicts, things plugin developers could do better to integrate with this etc?
esmi 7:49 pm on April 17, 2013 Permalink | Log in to Reply
I have to say, I’m really disappointed that there’s no mechanism for people to add captions for videos or provide text transcripts with audio files. come on, people! We need to be encouraging people to do this kind of stuff but unless WordPress provides the methods, it just won’t happen.
Scott Taylor 7:57 pm on April 17, 2013 Permalink | Log in to Reply
#patcheswelcome
Ipstenu (Mika Epstein) 8:18 pm on April 17, 2013 Permalink | Log in to Reply
Speaking as someone totally ignorant of this, how DO you add captions to videos? Can I include a transcript.txt file like I do for different video versions?
Joe Dolson 11:26 pm on April 17, 2013 Permalink | Log in to Reply
There are various formats for captions, but yes, essentially it amounts to referencing a text file with captions. Mediaelement.js supports .srt and .vtt caption formats, and they’re referenced as
In this context, you should treat the terms ‘subtitles’ and ‘captions’ synonymously, although technically they are different.
All the WP system needs to do for captions is provide a mechanism to upload them and auto-generate the relevant track elements, basically.
Joe Dolson 11:27 pm on April 17, 2013 Permalink | Log in to Reply
Damn. Lost the code. Go to http://mediaelementjs.com and you can see it there…
esmi 8:11 pm on April 17, 2013 Permalink | Log in to Reply
We’ve only just picked this up in the make.wordpress.accessible group but, yes, we will be trying to come up with some patches if we can
FranciscoAMK 8:19 pm on April 21, 2013 Permalink | Log in to Reply
Is the featured image set as the “poster” for the video post format?