CSS fundamentals
jared anderson
what is css?
a language for specifying how web documents are presented to users
CSS
- browser: user software used to consume the web
- document: a structured text file parsed by users' browser (HTML, XML or SVG)
- stylesheet: tells browser how to present the document to the person
the traditional web
https://developer.mozilla.org/en-US/docs/Learn/CSS/Introduction_to_CSS/How_CSS_works
grab doc
how it works
dom?
- The browser converts HTML and CSS into the DOM.
- The DOM represents the document in the computer's memory.
- It combines the document's content with its style.
- The browser displays the contents of the DOM
document object model: a tree-like structure where each element, attribute, and text become a DOM node in the structure
<p>
Let's use:
<span>Cascading</span>
<span>Style</span>
<span>Sheets</span>
</p>
P
├─ "Let's use:"
├─ SPAN
| └─ "Cascading"
├─ SPAN
| └─ "Style"
└─ SPAN
└─ "Sheets"
you write
browser parses
<p>
Let's use:
<span>Cascading</span>
<span>Style</span>
<span>Sheets</span>
</p>
document
p
"Let's use:"
span
span
span
"Cascading"
"Style"
"Sheets"
creating structure
span {
background: orange;
}
document
p
"Let's use:"
span
span
span
"Cascading"
"Style"
"Sheets"
css lets you "select" and style specific nodes
span {
border: 1px solid black;
background-color: lime;
}
+
=
css
vocabulary
.my-class {
background: blue;
color: white;
}
parts
selector
property
value
declaration
rule
rule
@import 'custom.css';
/* other at-rules:
@charset
@media
@document
@font-face
@supports
*/
at-rules
@media (min-width: 801px) {
body {
margin: 0 auto;
width: 800px;
}
}
nested statements
statements
/* stylesheet.css */
@import 'custom.css';
@media (min-width: 801px) {
body {
margin: 0 auto;
width: 800px;
}
}
stylesheet
Q:
- Approximately how many CSS properties are there?
- How many stylesheets can one document contain?
- How many stylesheets should one document contain?
A:
- 300+
- Practically unlimited
- Traditionally, as few as possible to limit network requests (a browser bottleneck)
properties, values & units
some memorization required
- 300+ properties
- "many" units (value types)
- numeric-based (em, px, %, rem, vh, etc)
- color-based: (rgb, rgba, hex, etc)
- functions: (calc, color functions, url, etc)
- more...
- infinite number of possible values
- something you'll need to learn for yourself
w3schools mdn is your best reference
syntax
comma separated
whitespace
-
spaces, tabs and new lines
-
added for readability
-
browser tends to ignore much of the whitespace inside your CSS
@media (min-width: 70em) {
body {
font-size: 130%;
}
}
@media (min-width: 70em) { body {font-size: 130%;} }
=
comments
Comments in CSS begin with /* and end with */.
shorthand properties
group of related properties -> shorthand property allowing you to set all related property values in a single declaration
shorthand properties
.my-class {
padding-top: 10px;
padding-right: 15px;
padding-bottom: 15px;
padding-left: 5px;
}
.my-class {
padding: 10px 15px 15px 5px;
}
shorthand properties
.my-class {
background-color: red;
background-image: url(bg-graphic.png);
background-position: 10px 10px;
background-repeat: repeat-x;
background-scroll: fixed;
}
.my-class {
background: red url(bg-graphic.png) 10px 10px repeat-x fixed;
}
shorthand properties
/*
shorthand properties:
font
background
padding
border
margin
flex
flex-flow
*/
selectors
selectors
- selector is a declarative description describing which nodes in the tree to "select" and style
span.i-need-space {
display: block;
margin: 20vh 0;
}
- document is a tree structure with nodes
selectors
four categories
- simple
- attribute
- pseudo
- combinators
#1 simple selectors
match elements based on their element type, class, or id
type/element selectors
/* All p elements are red */
p {
color: red;
}
/* All div elements are blue */
div {
color: blue;
}
<p>Good morning.</p>
<div>Go away!</div>
class selectors
/*
The element with the
class "first" is bolded
*/
.first {
font-weight: bold;
}
/*
All the elements with the class
"done" are strike through
*/
.done {
text-decoration: line-through;
}
<ul>
<li class="first done">
Create an HTML document
</li>
<li class="second done">
Create a CSS style sheet
</li>
<li class="third">
Link them all together
</li>
</ul>
id selectors
#polite {
font-family: cursive;
}
#rude {
font-family: monospace;
text-transform: uppercase;
}
<p id="polite">
"Good morning."
</p>
<p id="rude">
"Go away!"
</p>
universal selector
* {
padding: 5px;
}
#2 attribute selectors
match elements based on their attributes and attribute values
attributes?
<p data-qty="3" data-is-number>
Three
</p>
<date timestamp="2017-01-11">
January 11, 2017
</date>
attribute name
attribute value
- [attr] : all elements with the attribute attr, whatever its value.
- [attr=val] : all elements with the attribute attr, but only if its value is val.
- [attr~=val]: all elements with the attribute attr, but only if the value val is one of a space-separated list of values contained in attr's value (for example a single class in a space-separated list of classes.)
presence & value attribute selectors
substring value attribute selectors
- [attr|=val] : all elements with the attribute attr for which the value is exactly val or starts with val- (careful, the dash here isn't a mistake, this is to handle language codes.)
- [attr^=val] : all elements with the attribute attr for which the value starts with val.
- [attr$=val] : all elements with the attribute attr for which the value ends with val.
- [attr*=val] : all elements with the attribute attr for which the value contains the string val (unlike [attr~=val], this selector doesn't treat spaces as value separators but as part of the attribute value.)
[data-vegetable] {
color: green
}
Ingredients for my recipe:
<i lang="fr-FR">Poulet basquaise</i>
<ul>
<li data-quantity="1kg" data-vegetable>
Tomatoes
</li>
<li data-quantity="3" data-vegetable>
Onions
</li>
<li data-quantity="3" data-vegetable>
Garlic
</li>
<li data-quantity="700g" data-vegetable="not spicy like chili">
Red pepper
</li>
<li data-quantity="2kg" data-meat>
Chicken
</li>
<li data-quantity="optional 150g" data-meat>
Bacon bits
</li>
<li data-quantity="optional 10ml" data-vegetable="liquid">
Olive oil
</li>
<li data-quantity="25cl" data-vegetable="liquid">
White wine
</li>
</ul>
[data-vegetable="liquid"] {
background-color: goldenrod;
}
[data-vegetable~="spicy"] {
color: red;
}
[lang|=fr] {
font-weight: bold;
}
[data-vegetable*="not spicy"] {
color: green;
}
[data-quantity$="kg"] {
font-weight: bold;
}
[data-quantity^="optional"] {
opacity: 0.5;
}
#3 pseudo-classes
& pseudo-elements
these don't select actual elements, but rather certain parts of elements, or elements only in certain contexts.
pseudo-classes
- a keyword preceded by a colon (:)
- added on to the end of selectors
- selected elements only when in a certain state.
pseudo-classes example
/* These styles will style our link
in all states */
a {
color: blue;
font-weight: bold;
}
/* We want visited links to be the same color
as non visited links */
a:visited {
color: blue;
}
/* We highlight the link when it is
hovered (mouse), activated
or focused (keyboard) */
a:hover,
a:active,
a:focus {
color: darkred;
text-decoration: none;
}
pseudo-classes
pseudo-elements
- keywords preceded by two colons (::)
- added to the end of selectors
- selects a certain part of an element.
pseudo-elements example
/*
All elements with an attribute "href", which values
start with "http", will be added an arrow after its
content (to indicate it's an external link)
*/
[href^=http]::after {
content: '⤴';
}
pseudo-elements
#4 combinators
combining selectors to perform more fine-grained selections
combinator syntax
Combinators | Select |
---|---|
AB | matches both A and B at the same time. |
A B | matching B that is a descendant of an element matching A |
A > B | matching B that is a direct child of an element matching A |
A + B | matching B that is the next sibling of an element matching A |
A ~ B | matching B that is among the next sibling of an element matching A |
combinators pop quiz
table td, table > th {}
table thead th {}
table tbody td + td {}
table tbody td:last-child {}
.with-currency[lang="fr"] td:last-child::after {
content: ' €';
}
.thumbnail.is-big {
transform: scale(2);
}
the cascade
css, multiple inheritance & property conflict resolution
<p>
<span class="one">
Cascading
</span>
<span id="two" class="span two">
Style
</span>
<span class="three">
Sheets
</span>
</p>
span {
color: purple;
}
#two {
color: blue;
}
p:first-child span.two.two:nth-child(2) {
color: red;
}
span:nth-child(2) {
color: yellow;
}
* {
color: orange;
}
(not rule)
conflict resolution
the selector that wins out in the cascade depends on these three factors, listed in order of weight (least to most):
- Source order
- Specificity
- Importance
#1 source order
p {
color: red;
}
p {
color: blue;
}
when everything else is equal, rules defined later in a stylesheet win over rules defined beforehand.
#2 specificity
- a measure of how specific a selector is, in terms of how many elements it could match.
- the more specific a selector -- the fewer items it will match -- the more weight that rule has.
- The amount of specificity a selector has is based on something called the selector weight.
- selector weight has four different values, which can be thought of as thousands, hundreds, tens and ones:
0030 > 0009
#2 specificity
selector weight
- 1000s: 1 if the declaration is contained within a <style> tag or as part of a style attribute. Otherwise, 0.
- 100s: 1 for each id selector contained within the overall selector.
- 10s: 1 for each class selector, attribute selector or pseudo-class contained inside the overall selector.
- 1s: 1 for each element selector and pseudo-element contained inside the overall selector
Universal selector (*), combinators (+, >, ~, ' ') and negation pseudo-class (:not) have no effect on specificity.
#2 specificity
selector weight
#2 specificity
💩
if you are having specificity battles, that should be a smell that something is wrong.
consider adopting a system or strategy like CSS modules, BEM, atomic, ITCSS, OOCSS
#3 importance
don't use it!!!1
.💩 {
display: none !important;
}
conflict resolution
The only way to override this !important declaration would be to include another !important declaration of the same specificity, later in the source order.
conflict resolution
recap
- Source order
- Specificity
- Importance
conflict resolution system
100,000s
10,000s
1,000s
100s
10s
1s
!important
<style> style=
# id selectors
# class, pseudo class, attribute selectors
# element, pseudo-element selectors
source order
inheritance
some property values are inherited. some are not.
¯\_(ツ)_/¯
"common sense" is your reference. Or this:
controlling inheritance
set the value of property to adjust inheritance behavior
- inherit: be the same as that of its parent element.
- initial: be the same as the value set for that element in the browser's default style sheet
- unset: resets the property to its natural value, which means that if the property is naturally inherited it acts like inherit, otherwise it acts like initial.
box model
box model
- the foundation of layout on the Web
- each element is represented as a rectangular box
- each box's content, padding, border, and margin built up around one another like the layers of an onion
- as browser renders, it works out what styles are applied to the content of each box
- how big
- where boxes sit in relation to one another
- etc
box model
- width/height: set the width and height of the content box (text content and other boxes)
- padding: layer between the outer edge of the content box and the inner edge of the border.
- border: layer between the outer edge of the padding and the inner edge of the margin
- margin: outer area surrounding the CSS box, which pushes up against other CSS boxes
box types
- many different box types which changes the behavior
- box type changed by the `display` property
- block
- inline
- inline-block
- flex
- etc
must do
*, *:before, *:after {
box-sizing: border-box;
}
https://css-tricks.com/box-sizing/
challenges
what makes CSS hard?
- memorization required
- 300+ properties and growing
- always shifting browser support landscape
- knowing what is possible
- foundational knowledge required
- hard to scale
- managing globals
- managing the cascade
- specificity wars
- acquiring unorganized stylesheets
leveling up
improving at CSS
- write more CSS
scaling
the cascade and inheritance model are awesome until they're not...
strategies, conventions & tech
- atomic design
- ITCSS
- CSS modules
- BEM
- OOCSS
- etc
philosophy behind ITCSS
- settings: variables, definitions, etc (no output)
- tools: functions / mixins (no output)
- generic: resets, normalizations
- elements: base styles for "unclassed" elements (eg: H1 default styles)
- objects: class-based styles for elements (eg: diff types of H1)
- components: grouping components together (ie: widgets, patterns)
- trumps: nuclear overrides
philosophy behind ITCSS
- reach: top of triangle affects / has potential to affect more elements
- specificity: increase in specificity the further down the triangle
- explicitness: from (top) generic, low-level, unremarkable to (bottom) scoped and specific rules
the end :)
references
CSS Fundamentals
By Jared Anderson
CSS Fundamentals
- 1,530