CSS Myths
Published on
Common misconceptions of CSS - CSS gets a lot of stick, the internet is full of articles describing ways to fix one, or all of it's so called failings. Most of the time however, these criticisms are unfair, untrue or both.
Published on
Common misconceptions of CSS - CSS gets a lot of stick, the internet is full of articles describing ways to fix one, or all of it's so called failings. Most of the time however, these criticisms are unfair, untrue or both.
Published on
CSS gets a lot of stick, the internet is full of articles describing ways to fix one, or all of it's so called failings. Most of the time however, these criticisms are unfair, untrue or both. This post aims to highlight some of the common misconceptions or myths around CSS and it's capabilities.
So first of all CSS is not broken, it just isn't a programming language and so should not be expected to behave like one. Many of the CSS in JavaScript methodologies that have appeared over the past couple of years aim to 'fix' CSS by forcing it to behave in a more conventional programming way, in doing so some key CSS features are lost.
You can read more on the topic of broken CSS in these two awesome articles...
CSS is not easy, it may be seen as the simplest of the client side languages, but creating a maintainable CSS code base at scale is a difficult skill to master. Like no other front end language any changes made in CSS have the potential to affect the global landscape, meaning extra discipline and knowledge are required.
To work effectively a detailed understanding of key CSS features is essential:
The cascade determines which properties will be applied, and can be thought of as a way of resolving conflicting styles. Which selector wins out in the cascade depends on three factors:
On larger projects a misunderstanding of the cascade can lead to excessive use of the !important rule as well as unmaintainable CSS.
There are three origins of styles, each one has a level of importance used by the cascade to determine which properties will be applied.
This order can be reversed by using the !important rule allowing a property in the user style sheet to override a matching declaration in the author stylesheet.
Specificity comes into play if the importance of two declarations is the same. A 4 digit number is given to each selector, this number is derived from the 4 factors below, the selector with the higher specificity will be applied.
#nav .selected > a:hover // specificity = 0,1,2,1
.wrapper .box ul li // specificity = 0,0,2,2
The !important rule is not directly related to specificity as it does not have a value assigned to it. It does however automatically win out against any other selectors. The only way to override and !important deceleration is to use another !important declaration on a selector of equal or higher specificity.
Source order comes into play if the importance and specificity of two declarations is the same. Declarations that appear at the bottom of a style sheet will effectively overwrite any matching declarations from above.
CSS properties like font-family and color can be applied to a single element and be passed down to the elements children. Inheritance can be controlled using three CSS properties:
A directly targeted element will always take precedence over rules which an element inherits from its ancestor.
CSS is often compared unfavourably to the localised scoping features of JavaScript. A misunderstanding of the global scope leads to an overuse of the !important declarations and excessively long selectors (both of which introduce a new set of problems). However, the global by default feature of CSS is actually a great asset, if you know how to use it. The cascade and inheritance together determine how all elements will be styled, this allows you to create base level rules just once and have them applied across a projects code base.
Benefits of the CSS global scope include:
CSS, where required can be scoped, the simplest method for this would be by using double classes and a naming convention such as BEM to target a specific chunks of UI.
// default button
.button {
display: inline-block;
text-align: center;
background-color: #00823b;
color: #fff;
}
// success button
.button--success {
background-color: #005ea5;
}
// cancel button
.button--cancel {
background-color: $primary-color--featured;
}
You can also add scope to your CSS using custom properties. Custom properties, allow values to be saved and re-used throughout a project. In that respect they are similar to Sass or Less variables, but have the added bonus of being dynamically updated (More on this in section 9).
Custom properties are defined like this...
:root {
--button-color: #ffa600;
}
and used like this...
.button {
background-color: var(--button-color);
}
Custom properties can be scoped by declaring values inside a class or element. In the below example the value assigned to the buttons background color is changed for all elements within a header block.
:root {
--button-color: #ffa600;
}
header {
--button-color: #aaa19a;
}
.button {
background-color: var(--button-color);
}
It is true that an over-reliance on the !important rule can be a warning sign for underlying issues with the CSS architecture, but providing it is used responsibly and for it's intended purposes it is perfectly fine to use.
Firstly by using the !important declaration rules from the author style sheet are able to be overwritten in the user style sheet. This is particularly useful for accessibility enhancements such as increasing font size or re-adding the underline property to anchors.
!important can also be used effectively in the author style sheet itself, the most common use case is for utility (helper) classes. Utility classes are often used to set up base rules for a project, these are rules which should always be applied, yet are usually defined at the top of a style sheet and have low specificity.
.margin-bottom {
margin-bottom: 10px;
}
The specificity of the selector above is just 0,0,1,0 and so the value could be easily overwritten further down the style sheet. To address this and make helper classes more resilient the !important rule can be applied.
.margin-bottom {
margin-bottom: 10px!important;
}
Finally, although not a valid long term use case the !important rule can be very useful for getting quick fixes shipped to production. There isn't always time for a detailed assessment of the CSS structure or for re-factoring large chunks of code to fix a style bug. In these cases it can be helpful to use !important as a make shift fix, providing the real work is addressed afterwards. It is usually helpful to keep these styles in a separate CSS file, csswizardry.com has more information on this concept.
Progressive enhancement promotes the idea of adding extra functionality for modern browsers and devices, only after delivering core content and functionality to all bowsers and devices. This is often achieved with JavaScript feature detection.
It is possible to detect support for a property within CSS without the need to include a third-party script such as Modernizr or Autoprefixer. The @supports rule is a conditional rule which allows for different styles to be applied depending on browser support.
By defining core css properties at the top of a selector you ensure they are rendered in all browsers, extra 'nice to have' features can be conditionally added underneath without effecting this core styling.
An example would be CSS blend modes which are used to add styling to backgrounds and images. This could create problems with the readability of overlaying text in browsers that don't support blend modes.
By using @supports you can ensure browsers without support are served a more appropriate font-color.
.banner {
background-image: url(image-url);
color: black
@supports (background-blend-mode: multiply) {
.banner {
background-color: green;
background-blend-mode: multiply;
color: white
}
}
You can also check for features which are not supported as well as combine properties with either 'and' or 'or' statements.
CSS can do more than simply apply the aesthetics to an applications UI. It can also play a role in enhancing the accessibility and usability of a project.
CSS can among other things also be used to...
a[target=_blank]::after {
display: inline-block;
overflow: hidden;
width: 0;
height: 0;
white-space: nowrap;
content: '(opens new window)';
}
Shorthand properties allow multiple values to be set simultaneously and are a nice way of keeping your style sheets concise and readable. There are currently 6 shorthand property groups:
There can be performance gains from using the shorthand syntax correctly, for example...
margin-top: 10px;
margin-right: 0;
margin-bottom: 10px;
margin-left: 0;
could be written as...
margin: 10px 0;
However, it is important to note that a property which is not specified is automatically set to its initial value. This can lead to properties needing to be overwritten further down the style sheet. For example...
html {
font: 16px helvetica neue
}
will actually set...
html {
font-style: normal;
font-variant: normal;
font-weight: normal;
font-size: 16px;
line-height: normal;
font-family: helvetica neue;
}
On larger applications problems can arise from setting too many styles to soon, in the example above it would be more efficient to set only the values that we are using...
html {
font-size: 16px;
font-family: helvetica neue;
}
CSS is defined as a markup language not a programing or scripting language, but it does come with some basic functions included The most common functions deal with colour manipulation and animations, functions like linear-gradient(), blur(), translate() and rotate().
One of the more powerful functions is calc() which can be used to replace number values with simple mathematical equations. Calc() also allows for mixed units making it an effective way to build native responsive layouts.
.sidebar {
width: 300px;
}
.content {
width: calc(100% - 300px);
}
Using custom properties can open up new posabilities for functions within CSS. Unlike Sass or Less variables, which compile to set values in CSS, custom properties can be updated dynamically. This allows for direct interaction between CSS and JavaScript. The below JavaScript allows a CSS custom property value to be retrived or set...
var backgroundcolor = bodystyles.getpropertyvalue('--background-color'); // retrieve
body.style.setproperty('--background-color', 'black'); // set
Example use cases for dynamic CSS include Generating colors, Contrast theming and Animation
There are literally hundreds of CSS frameworks, grids and methodologies available to speed up development and help lay the foundations for scalable well structured CSS. These frameworks can be hugely beneficial but are often heavily criticised.
A few common criticisms are:
Despite these concerns frameworks can help improve a project. The important thing is that you understand how and why the framework works, and that it adds value to your project. It's important that the framework is seen as a helper and not as an essential component. It's wise to use only the parts of the framework that you need, strip out the excess and make changes where required.
In summary CSS is not a bad programing language, its a very good style sheet language. The features of CSS are not secret, anyone can read up on and learn to write good CSS, if you choose not to it can become a nightmare.