├── .gitignore ├── README.md └── img ├── box_model.png ├── box_model_box-sizing.png ├── box_model_box_types.png ├── box_model_positioning_scheme.png ├── cascade.png ├── css_processing_values.png ├── css_processing_values_2.png ├── css_rendering.png ├── inheritance.png ├── terminology.png └── unit_conversion.png /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # How does CSS work behind the scene? 2 | > ⚠ These are my notes on how CSS works behind the scene. If you find 3 | them helpful, great fork it, copy it whatever but don't fully rely on it because 4 | some info may not be complete or explained clearly. These are NOT official docs! 5 | 6 | ## Alright, Lets Start 7 | Before we move on with how CSS works there are some thing to keep in mind while 8 | designing a website. Keeping these things in mind will help you understand why 9 | you need to know about the behind the scene and vice versa. 10 | 11 | The important pillars of a modern web design are: 12 | * Responsive Design 13 | * Maintainable and scalable code 14 | * Performance 15 | 16 | ### Responsive Design 17 | Responsive design is the modern standard. Every modern website is responsive 18 | and there is a good reason for it. Many people visit websites on smart phones 19 | and websites have to adapt. Following are the fundamentals of a responsive 20 | design: 21 | * Fluid layouts 22 | * Media queries 23 | * Responsive images 24 | * Correct units 25 | * Desktop-first or mobile-first approach 26 | 27 | ### Maintainable and Scalable Code 28 | You should write your code in a way so it can be easily read, maintained and 29 | scaled also your code should be reusable. To write maintainable and scalable 30 | code your code should have following characteristics: 31 | * Clean 32 | * Easy to understand 33 | * Easy to grow 34 | * Reusable 35 | * Organisable 36 | * Correct naming - understandable classes names 37 | * Good HTML structure 38 | 39 | ### Performance 40 | Performance is very important. Nobody wants to wait for a website to load 41 | especially when they are on a smart phone. Fundamentals of making a website 42 | faster: 43 | * Less HTTP request 44 | * Less code 45 | * Compress your code 46 | * Use a CSS preprocessors 47 | * Less images 48 | * Compress images 49 | 50 | 51 | ## What Happens to CSS When a Page is Loaded 52 | ![what happens to CSS](img/css_rendering.png) 53 | 54 | ## How is CSS Parsed - Cascade and Specificity 55 | ### Terminology 56 | ![terminology](img/terminology.png) 57 | 58 | ### The Cascade 59 | The Cascade is an algorithm that defines how to combine property values 60 | originating from different sources. It lies at the core of CSS, as emphasized 61 | by the name: *Cascading Style Sheets*. [Source](https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade) 62 | 63 | Basically the Cascade combines different stylesheets and resolves conflicts 64 | between different CSS rules and declarations when more than one rule applies to 65 | a certain element. It simply selects CSS declarations and determines correct 66 | values for CSS properties. CSS declarations originates from different 67 | origins/sources: 68 | * Author stylesheets -> Declared by the designer, the code you write. The most 69 | common type style sheet. 70 | * User stylesheets -> The user (or reader) of the website can choose to 71 | override styles through browser. 72 | * User-agent stylesheets -> The browser has a basic style sheet that gives a 73 | default style to any document. 74 | 75 | In order to resolve conflicts the Cascade looks at importance (`!important`), 76 | selectors specificity, and source order of conflicting declarations. 77 | 78 | ![what happens to CSS](img/cascade.png) 79 | 80 | > If the importance was the same for all selectors the Cascade will look at 81 | specificity to apply the styles of the most specific selectors. If all the 82 | selectors had the same specificity then it will look at source order and apply 83 | the last declared styles. 84 | 85 | #### Examples 86 | #### Importance 87 | ```css 88 | .button { 89 | color: #fff; 90 | font-size: 16px; 91 | background-color: #333 !important; 92 | } 93 | 94 | #nav .button { 95 | background-color: #999; 96 | } 97 | /* #333 will be applied NOT #999 */ 98 | ``` 99 | 100 | #### Specificity 101 | ```css 102 | .button { 103 | color: #fff; 104 | font-size: 16px; 105 | background-color: #333; 106 | } /* (inline, IDs, Classes, Elements) */ 107 | /* ( 0 , 0 , 1 , 0 ) */ 108 | 109 | nav#nav div.pull-right .button { 110 | background-color: #999; 111 | } /* (inline, IDs, Classes, Elements) */ 112 | /* ( 0 , 1 , 2 , 2 ) */ 113 | 114 | a { 115 | background-color: #666; 116 | } /* (inline, IDs, Classes, Elements) */ 117 | /* ( 0 , 0 , 0 , 1 ) */ 118 | 119 | /* :hover is pseudo-class therefore it counts as a class*/ 120 | #nav a.button:hover { 121 | background-color: #999; 122 | } /* (inline, IDs, Classes, Elements) */ 123 | /* ( 0 , 1 , 2 , 1 ) */ 124 | ``` 125 | Now to determine the specificity we first look at inline styles if there are 126 | any. For all the above cases there are no inline styles therefore it's 0 for 127 | all. Then we look IDs if there are any. Then we look at classes and lastly the 128 | elements. In the example above `(0, 0, 1, 0)` and `(0, 0, 0, 1)` can be 129 | thrown out because they're the least specific. But `(0, 1, 2, 1)` and 130 | `(0, 1, 2, 2)` are the ones to look at. So `(0, 1, 2, 1)` has one ID, 131 | two classes and one element which makes it very specific but `(0, 1, 2, 2)` 132 | has one ID, two classes and 2 elements which is the most specific one. 133 | Therefore the styles of the second selector will be applied and other styles will 134 | be ignored. 135 | 136 | If the specificity from all the selectors was the same then 'source order' rule 137 | will be applied. Which means the last declared styles will be applied. 138 | 139 | ```css 140 | nav#nav div.pull-right .button { 141 | background-color: #666; 142 | } /* (inline, IDs, Classes, Elements) */ 143 | /* ( 0 , 1 , 2 , 2 ) */ 144 | 145 | #nav a.button:hover { 146 | background-color: #999; 147 | } /* (inline, IDs, Classes, Elements) */ 148 | /* ( 0 , 1 , 2 , 1 ) */ 149 | 150 | /* 151 | hover will not work because it's specificity is lower than the selector 152 | above. To make the hover work we will have to use the same specificity like so: 153 | */ 154 | nav#nav div.pull-right .button:hover { 155 | background-color: #999; 156 | } 157 | ``` 158 | 159 | ##### Key takeaways: 160 | * CSS declarations marked with `!important` have the highest priority. 161 | * But using `!important` is bad practice. It's better to rely on specificities 162 | than to just use `!important`. The code should be maintainable! 163 | * Inline styles will always have priority over styles in external stylesheets. 164 | * A selector that contains 1 ID is more specific than one with 1000 classes. 165 | * A selector that contains 1 class is more specific than one with 1000 element selectors. 166 | * The universal selector `*` has no specificity value `(0, 0, 0, 0)`. 167 | * Rely more on specificity than on the order of selectors. 168 | * But, use source order when working with 3rd-party styles -- always put author 169 | stylesheets last. 170 | 171 | ### How CSS Values are Processed 172 | ![how css values are processed](img/css_processing_values.png) 173 | ![how css values are processed](img/css_processing_values_2.png) 174 | 175 | ### How Units are Converted From Relative to Absolute (Pixels) 176 | ![how units are converted](img/unit_conversion.png) 177 | 178 | ##### Key takeaways: 179 | * Each property has an initial value, used if no specific value is declared 180 | (and if there is no inheritance). 181 | * Browsers specify a root font-size for each page (usually 16px). 182 | * Percentages and relative values always converted to pixels. 183 | * Percentages are measured relative to their parent's font-size, if used to 184 | specify font-size. 185 | * Percentages are measured relative to their parent's width, if used to specify 186 | lengths. 187 | * em are measured relative to their parent font-size, if used to specify 188 | font-size. 189 | * em are measured relative to the current font-size, if used to specify 190 | lengths. 191 | * rem are always measured relative to the document's root font-size. 192 | * vh and vw are simply percentage measurements of the viewport's height and 193 | width. 194 | 195 | ### Inheritance in CSS 196 | ![inheritance in css](img/inheritance.png) 197 | 198 | ##### Key takeaways: 199 | * Inheritance passes the values for some specific properties from parents to 200 | children. Should be used to write maintainable code. 201 | * Properties related to text are inherited: `font-family`, `font-size`, `color` etc. 202 | * Computed values of a property are inherited, NOT the declared value. 203 | * Inheritance of a property only works if no value is declared for that 204 | property. 205 | * The `initial` keyword resets a property to its initial value. 206 | * The `inherit` keyword forces inheritance on a certain property. Example: 207 | ```css 208 | * { 209 | margin: 0; 210 | padding: 0; 211 | box-sizing: inherit; /* Will be inherited from body */ 212 | } 213 | 214 | body { 215 | box-sizing: border-box; 216 | } 217 | ``` 218 | 219 | ## Now it's Time to Use What We've Learned 220 | The most important thing for us to do is to write our CSS in a way that is 221 | clean, maintainable and scalable -- somewhat dynamic. To achieve that we have 222 | to use relative units to avoid writing lots of CSS. Repetitively using same 223 | selectors with different properties and value declarations leads to messy and 224 | unstable code. Also if we don't use correct units then it'll lead to using 225 | unnecessary media queries, thus messy and unmaintainable code. Correct units 226 | are crucial to responsive design. 227 | 228 | To make things easy we'll use `rem` units. Which means relative to the 229 | root. The root `font-size` is set in the `html` selector. We will use 230 | font size to be `10px` instead of `16px`. It'll make things super easy 231 | for us. What root font size `10px` means is that `1rem = 10px`. Because 232 | 10 is a round number what we can do is to divide each pixels values by `10px` 233 | and it'll give us nice rounded `rem` values e.g `16px / 10px = 1.6rem`. 234 | 235 | #### Example 236 | ```css 237 | html { 238 | font-size: 10px; 239 | } 240 | 241 | body { 242 | padding: 3rem; /* 30px / 10px = 3rem */ 243 | } 244 | 245 | .logo-box { 246 | position: absolute; 247 | top: 4rem; /* 40px / 10px = 4rem */ 248 | left: 4rem; /* 40px / 10px = 4rem */ 249 | } 250 | 251 | .logo { 252 | height: 3.5rem; /* 35px / 10px = 3.5rem */ 253 | } 254 | 255 | .heading-primary { 256 | margin-bottom: 6rem; /* 60px / 10px = 6rem */ 257 | } 258 | 259 | .heading-primary-main { 260 | font-weight: 400; 261 | font-size: 6rem; /* 60px / 10px = 6rem */ 262 | letter-spacing: 3.5rem; /* 35px / 10px = 3.5rem */ 263 | } 264 | 265 | .heading-primary-sub { 266 | font-weight: 700; 267 | font-size: 2rem; /* 20px / 10px = 2rem */ 268 | letter-spacing: 1.75rem; /* 17.5px / 10px = 1.75rem */ 269 | } 270 | 271 | .button { 272 | padding: 1.5rem 4rem; /* 15px / 10 = 1.5rem - 40px / 10px = 4rem */ 273 | } 274 | ``` 275 | 276 | As you can see we can declare everything in `rem` relative to the root 277 | `font-size`. If we want to make them bigger or smaller the only thing we 278 | have to do is to change the root `font-size` and that's it. We don't have 279 | to write thousands of media queries, change every value by hand pixel by pixel, 280 | rewrite each selector and redeclare values. `rem` makes our lives easier. 281 | 282 | BUT there is still one problem and that is our `font-size` is set to 283 | `10px` which is an absolute value. That means is that our values are still 284 | relative to an absolute value. If you've heard of "Web Accessibility" we are 285 | excluding people with disabilities with our `font-size` set to `10px` 286 | which is a poor design choice. If there's someone with limited eyesight and 287 | want to change the default font size of the browser or zoom-in or out then 288 | they'll not be able to do that. 289 | 290 | > Web accessibility means that websites, tools, and technologies are designed and 291 | developed so that people with disabilities can use them. More specifically, 292 | people can: perceive, understand, navigate, and interact with the Web. 293 | [Source](https://www.w3.org/WAI/fundamentals/accessibility-intro/) 294 | 295 | #### Solution 296 | We can set the `font-size` to percentage. `100%` would mean `16px` as it's default. 297 | But we want our `font-size` to be `10px`. That can be easily calculated. 298 | `10/16 = 0.625 * 100 = 62.5%`. So we set our root font size to be 62.5%.
299 | Now when the user changes the default font size of the browser to for example 300 | 16px that would be `0.625*16 = 10px` likewise 20px would be `0.625*20 = 12.5px` so 301 | it will change accordingly and our website will be accessible to everyone. 302 | 303 | ## The Visual Formatting Model 304 | > The *CSS visual formatting model* is an algorithm that processes a document and 305 | displays it on visual media. This model is a basic concept of CSS. The visual 306 | formatting model transforms each element of the document and generates zero, one, 307 | or several boxes that conform to the CSS box model. The layout of each box is 308 | defined by: 309 | > * The dimensions of the box: precisely defined or constrained, or not 310 | > * The type of box: inline, inline-level, atomic inline-level, block 311 | > * The positioning scheme: in the normal flow, a float, or absolute positioning 312 | > * The other elements in the tree: its children or neighbors 313 | > * The viewport size and position 314 | > * Intrinsic dimensions of contained images 315 | > * Other external information 316 | > 317 | >The model renders a box in relation to the edge of its containing block. Usually, 318 | a box establishes the containing block for its descendants. However, a box is not 319 | constrained by its containing block; when a box's layout goes outside the containing 320 | block, it is said to overflow. [Source](http://man.hubwiz.com/docset/CSS.docset/Contents/Resources/Documents/developer.mozilla.org/en-US/docs/Web/Guide/CSS/Visual_formatting_model.html) 321 | 322 | To understand what *Containing Block* is and how it's determined read [this 323 | article](https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block). 324 | 325 | So basically the visual formatting model algorithm calculates boxes and 326 | determines the layout of these boxes, for each element in the render tree 327 | (divs, paragraphs, images etc), in order to determine the final layout 328 | of the page. Every element is represented by a box on the page. So the whole 329 | layout/ the fully rendered page is made up of boxes. When a box is generated 330 | each box is divided into four areas: 331 | 1. Content area 332 | 2. Padding area 333 | 3. Border area 334 | 4. Margin area 335 | 336 | ### The Box Model 337 | ![box model](img/box_model.png) 338 | 339 | #### The Box Model: Width and Height 340 | ``` 341 | Total width = right border + right padding + specified width + left padding + 342 | left border 343 | 344 | Total height = top border + top padding + specified height + bottom padding + 345 | bottom border 346 | 347 | Example: height = 0 + 20px + 100px + 20px + 0 = 140px 348 | ``` 349 | #### The Box Model: `box-sizing: border-box;` 350 | When we set `box-sizing` to `border-box` the height and width will be declared 351 | for the entire box including padding and the border, not just for the content 352 | area. In other words the border and padding will not be added to the total 353 | width and total height but rather reduced to declared width and height. 354 | 355 | ![box model box-sizing](img/box_model_box-sizing.png) 356 | 357 | Total width = ~~right border~~ + ~~right padding~~ + specified width + ~~left padding~~ + 358 | ~~left border~~ 359 | 360 | Total height = ~~top border~~ + ~~top padding~~ + specified height + ~~bottom padding~~ + 361 | ~~bottom border~~ 362 | 363 | Example: height = ~~0~~ + ~~20px~~ + 100px + ~~20px~~ + ~~0~~ = 100px 364 | 365 | As you can see in the above example the total height is not `140px` but 366 | rather `100px` because padding is not added to the height but reduced in order 367 | to be included in the height. 368 | 369 | #### The Box Model: Box Types 370 | ![box model box types](img/box_model_box_types.png) 371 | 372 | #### The Box Model: Positioning Scheme 373 | ![box model positioning scheme](img/box_model_positioning_scheme.png) 374 | 375 | ### Stacking Context 376 | Stacking context determines in which order elements are rendered on the page. 377 | Stacking context can be created by various properties but the most common 378 | property is `z-index`. Stacking context are simply layers bottom layers are 379 | painted first and other appear on top of each other. Elements with lower 380 | `z-index` appear at the bottom and elements with higher `z-index`appear on the 381 | top. 382 | ``` 383 | _______________ -> z-index: 3; position: relative; 384 | 385 | _______________ -> z-index: 2; position: absolute; 386 | 387 | _______________ -> z-index: 1; position: relative; 388 | ``` 389 | Not only `z-index` creates stacking context but also `opacity` of values different 390 | from one another, `transforms` and `filters` also create stacking context. 391 | 392 | ## CSS (SASS) Architecture 393 | ### The 7-1 Pattern 394 | ``` 395 | sass/ 396 | | 397 | |– base/ 398 | | |– _reset.scss # Reset/normalize 399 | | |– _typography.scss # Typography rules 400 | | ... # Etc… 401 | | 402 | |– components/ 403 | | |– _buttons.scss # Buttons 404 | | |– _carousel.scss # Carousel 405 | | |– _cover.scss # Cover 406 | | |– _dropdown.scss # Dropdown 407 | | ... # Etc… 408 | | 409 | |– layout/ 410 | | |– _navigation.scss # Navigation 411 | | |– _grid.scss # Grid system 412 | | |– _header.scss # Header 413 | | |– _footer.scss # Footer 414 | | |– _sidebar.scss # Sidebar 415 | | |– _forms.scss # Forms 416 | | ... # Etc… 417 | | 418 | |– pages/ 419 | | |– _home.scss # Home specific styles 420 | | |– _contact.scss # Contact specific styles 421 | | ... # Etc… 422 | | 423 | |– themes/ 424 | | |– _theme.scss # Default theme 425 | | |– _admin.scss # Admin theme 426 | | ... # Etc… 427 | | 428 | |– abstracts/ 429 | | |– _variables.scss # Sass Variables 430 | | |– _functions.scss # Sass Functions 431 | | |– _mixins.scss # Sass Mixins 432 | | |– _helpers.scss # Class & placeholders helpers 433 | | 434 | |– vendors/ 435 | | |– _bootstrap.scss # Bootstrap 436 | | |– _jquery-ui.scss # jQuery UI 437 | | ... # Etc… 438 | | 439 | | 440 | `– main.scss # Main Sass file 441 | ``` 442 | [Source](https://sass-guidelin.es/#the-7-1-pattern) 443 | -------------------------------------------------------------------------------- /img/box_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xkhan/how-css-works-notes/15e9eb626c87c5c8a8694e27db5f844e662fae35/img/box_model.png -------------------------------------------------------------------------------- /img/box_model_box-sizing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xkhan/how-css-works-notes/15e9eb626c87c5c8a8694e27db5f844e662fae35/img/box_model_box-sizing.png -------------------------------------------------------------------------------- /img/box_model_box_types.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xkhan/how-css-works-notes/15e9eb626c87c5c8a8694e27db5f844e662fae35/img/box_model_box_types.png -------------------------------------------------------------------------------- /img/box_model_positioning_scheme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xkhan/how-css-works-notes/15e9eb626c87c5c8a8694e27db5f844e662fae35/img/box_model_positioning_scheme.png -------------------------------------------------------------------------------- /img/cascade.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xkhan/how-css-works-notes/15e9eb626c87c5c8a8694e27db5f844e662fae35/img/cascade.png -------------------------------------------------------------------------------- /img/css_processing_values.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xkhan/how-css-works-notes/15e9eb626c87c5c8a8694e27db5f844e662fae35/img/css_processing_values.png -------------------------------------------------------------------------------- /img/css_processing_values_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xkhan/how-css-works-notes/15e9eb626c87c5c8a8694e27db5f844e662fae35/img/css_processing_values_2.png -------------------------------------------------------------------------------- /img/css_rendering.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xkhan/how-css-works-notes/15e9eb626c87c5c8a8694e27db5f844e662fae35/img/css_rendering.png -------------------------------------------------------------------------------- /img/inheritance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xkhan/how-css-works-notes/15e9eb626c87c5c8a8694e27db5f844e662fae35/img/inheritance.png -------------------------------------------------------------------------------- /img/terminology.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xkhan/how-css-works-notes/15e9eb626c87c5c8a8694e27db5f844e662fae35/img/terminology.png -------------------------------------------------------------------------------- /img/unit_conversion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xkhan/how-css-works-notes/15e9eb626c87c5c8a8694e27db5f844e662fae35/img/unit_conversion.png --------------------------------------------------------------------------------