Slide 1

Slide 1 text

CSS for Software Engineers for CSS Developers Harry Roberts – SmashingConf Freiburg – September 2015

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

1959

Slide 4

Slide 4 text

The First Modern Programming Language

Slide 5

Slide 5 text

“ FLOW-MATIC FLOW-MATIC, originally known as B-0, was the first English-like data processing language. It was developed for the UNIVAC I at Remington Rand under Grace Hopper during the period from 1955 until 1959.

Slide 6

Slide 6 text

The First Programming Language FLOW-MATIC. The first modern, electronic programming language. 1955–1959. Developed by Grace Hopper. wikipedia.org/wiki/FLOW-MATIC

Slide 7

Slide 7 text

“ FLOW-MATIC … Rand management considered the idea unfeasible. In early 1955, she and her team wrote a specification for such a programming language and implemented a prototype.

Slide 8

Slide 8 text

1959 2015 1990 1996

Slide 9

Slide 9 text

1959 2015 1990 1996 FLOW-MATIC Me CSS Mum and Dad Sister

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

1959 2015 1990 1996 FLOW-MATIC Me CSS Mum and Dad Sister

Slide 12

Slide 12 text

1959 2015 1996

Slide 13

Slide 13 text

A 37-Year Head Start All that wisdom! We should get as much from their head start as we can. The time between the first modern programming language and CSS is greater than the time between CSS and now. Software engineers have been writing code for 37 years longer than front-end developers have.

Slide 14

Slide 14 text

DRY/Single Source of Truth

Slide 15

Slide 15 text

“ Don’t Repeat Yourself Every piece of knowledge must have a single, unambiguous, authoritative representation within a system. — wikipedia.org/wiki/Don't_repeat_yourself

Slide 16

Slide 16 text

Don’t Repeat Yourself Every discrete piece of information should exist only once. You shouldn’t need to make the same change several times. Repetition is extra overhead: more to maintain, to go wrong. Increases cognitive overhead. Contributes to bloat.

Slide 17

Slide 17 text

Don’t Repeat Yourself .u-margin-top { margin-top: 12px; } .u-margin-right { margin-right: 12px; } .u-margin-bottom { margin-bottom: 12px; } .u-margin-left { margin-left: 12px; }

Slide 18

Slide 18 text

Don’t Repeat Yourself .u-margin-top { margin-top: 12px; } .u-margin-right { margin-right: 12px; } .u-margin-bottom { margin-bottom: 12px; } .u-margin-left { margin-left: 12px; } We’ve typed the same value four times.

Slide 19

Slide 19 text

Don’t Repeat Yourself $unit: 12px; .u-margin-top { margin-top: $unit; } .u-margin-right { margin-right: $unit; } .u-margin-bottom { margin-bottom: $unit; } .u-margin-left { margin-left: $unit; } Much better! A single source of truth.

Slide 20

Slide 20 text

Don’t Repeat Yourself .page-title { font-family: "Custom Font", sans-serif; font-weight: 700;
 } .btn { font-family: "Custom Font", sans-serif; font-weight: 700;
 } .pagination { font-family: "Custom Font", sans-serif; font-weight: 700;
 }

Slide 21

Slide 21 text

Don’t Repeat Yourself .page-title { font-family: "Custom Font", sans-serif; font-weight: 700;
 } .btn { font-family: "Custom Font", sans-serif; font-weight: 700;
 } .pagination { font-family: "Custom Font", sans-serif; font-weight: 700;
 } Thematically related but repeated.

Slide 22

Slide 22 text

Don’t Repeat Yourself @mixin custom-font() { font-family: "Custom Font", sans-serif; font-weight: 700; } 
 .page-title { @include custom-font();
 } .btn { @include custom-font();
 } .pagination { @include custom-font();
 } Argumentless mixins are perfectly okay.

Slide 23

Slide 23 text

Don’t Repeat Yourself @mixin custom-font() { font-family: "Custom Font", sans-serif; font-weight: 700; } 
 .page-title { @include custom-font();
 } .btn { @include custom-font();
 } .pagination { @include custom-font();
 } Gives the exact same output, but at least we haven’t duplicated anything manually.

Slide 24

Slide 24 text

“ Single Source of Truth […] the practice of structuring information models and associated schemata such that every data element is stored exactly once. — wikipedia.org/wiki/Single_Source_of_Truth

Slide 25

Slide 25 text

Single Source of Truth The more philosophical principle behind DRY. Key data should only exist once in source. Increases confidence. Prevents anomalies and disparity. Makes changes simpler. Keeps your house in order.

Slide 26

Slide 26 text

Confusion DRY in source, not in production. Not about avoiding repetition… It’s about avoiding repeating yourself. Automation of repetition is fine.

Slide 27

Slide 27 text

“ Confusion If you manually type a declaration 50 times in a project, you are repeating yourself: this is not DRY. If you can generate that declaration 50 times without having to manually repeat it, this is DRY: you are generating repetition without actually repeating yourself. This is quite a subtle but important distinction to be aware of. — csswz.it/1ytQkxp

Slide 28

Slide 28 text

Confusion .btn { color: white; font-weight: bold;
 } .calendar__title { font-size: 14px; font-weight: bold; } .message { font-weight: bold; }

Slide 29

Slide 29 text

Confusion .btn { color: white; font-weight: bold;
 } .calendar__title { font-size: 14px; font-weight: bold; } .message { font-weight: bold; } This is purely coincidental. Don’t try to DRY it out.

Slide 30

Slide 30 text

Confusion Don’t DRY if it’s repeated coincidentally. Repetition in compiled code is fine. Just avoid duplicating data in source. Going too far creates awkward and confusing structures in your code.

Slide 31

Slide 31 text

DRY/Single Source of Truth Use a preprocessor to store key data in variables. Make use of mixins to generate repetition for you. Abstract design patterns out into reusable objects. Do not DRY anything that is purely coincidental. Repetition is better than the wrong abstraction.

Slide 32

Slide 32 text

The Single Responsibility Principle

Slide 33

Slide 33 text

“ The Single Responsibility Principle […] the single responsibility principle states that every class should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class. — wikipedia.org/wiki/Single_responsibility_principle

Slide 34

Slide 34 text

The Single Responsibility Principle AKA: Do one thing, one thing only, and one thing well. Break bigger monoliths down into individual concerns. Easier to reason about. Provides higher composability.

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

The Single Responsibility Principle Subway is the epitome of SRP. Break things down into their smallest possible parts. Ensure each part fulfils its responsibility very well. Combine responsibilities to create complex components. Swap out, remove, or add discrete parts. Helps you Separate your Concerns. Gives you incredible opportunity and flexibility.

Slide 38

Slide 38 text

6,442,450,944

Slide 39

Slide 39 text

6,442,450,944 6.4bn possible sandwich combinations. All by offering individual ingredients. Smaller pieces allow for greater composition. csswz.it/1XKydl8

Slide 40

Slide 40 text

The Single Responsibility Principle #sandwich {
 bread: white; meat: chicken; salad: lettuce, onion, tomato; sauce: mayonnaise;
 }
...

Slide 41

Slide 41 text

The Single Responsibility Principle #sandwich {
 bread: white; meat: chicken; salad: lettuce, onion, tomato; sauce: mayonnaise;
 }
...
This is a monolith. It’s difficult to change, swap, or remove things.

Slide 42

Slide 42 text

The Single Responsibility Principle .bread, .bread--white {} .chicken {}
 .lettuce {} .onion {} .tomato {} .mayonnaise {}
...
Perfect! Now we can make our own sandwich from the ingredients we want.

Slide 43

Slide 43 text

The Single Responsibility Principle .bread, .bread--white {} .chicken {}
 .lettuce {} .onion {} .tomato {} .mayonnaise {}
...
No tomato? No problem!

Slide 44

Slide 44 text

The Single Responsibility Principle Provide developers with the ingredients. Let them make the meals. Let’s look at a more realistic example…

Slide 45

Slide 45 text

The Single Responsibility Principle .btn-login { display: inline-block; padding: 2em; background-color: green; color: white;
 }

Slide 46

Slide 46 text

The Single Responsibility Principle .btn-login { display: inline-block; padding: 2em; background-color: green; color: white;
 } Mixing responsibilities. Base. Structural. Cosmetic.

Slide 47

Slide 47 text

The Single Responsibility Principle .btn { display: inline-block;
 } .btn--large { padding: 2em; } .btn--positive { background-color: green; color: white;
 }

Slide 48

Slide 48 text

The Single Responsibility Principle .btn { display: inline-block;
 } .btn--large { padding: 2em; } .btn--positive { background-color: green; color: white;
 } That’s better.

Slide 49

Slide 49 text

The Single Responsibility Principle .btn { ... } .btn--large { ... } .btn--small { ... } .btn--positive { ... } .btn--negative { ... } .btn--full { ... } Plus now we can combine these classes with others to make lots of varieties of button.

Slide 50

Slide 50 text

The Separation of Concerns

Slide 51

Slide 51 text

“ The Separation of Concerns […] It is, that one is willing to study in depth an aspect of one’s subject matter in isolation for the sake of its own consistency […] But nothing is gained—on the contrary! —by tackling these various aspects simultaneously. It is what I sometimes have called ‘the separation of concerns’ […] it does not mean ignoring the other aspects, it is just doing justice to the fact that from this aspect’s point of view, the other is irrelevant. It is being one- and multiple-track minded simultaneously. — wikipedia.org/wiki/Separation_of_concerns

Slide 52

Slide 52 text

The Separation of Concerns Each thing responsible for itself and nothing more. Reason about and study features in isolation. In CSS: Only bind CSS onto CSS-based classes only. Don’t write DOM-like selectors. Don’t bind CSS onto data-* attributes. Don’t bind JS onto CSS classes.

Slide 53

Slide 53 text

The Separation of Concerns // Binding CSS onto accessibility hints. [role="nagivation"] { ... } // Putting DOM information into our CSS. header nav ul li a { ... } // Using HTML to provide cosmetics. // Binding JS onto styling hooks. document.getElementsByClassName('nav');

Slide 54

Slide 54 text

The Separation of Concerns 


Slide 55

Slide 55 text

The Separation of Concerns 


Slide 56

Slide 56 text

The Separation of Concerns [role="navigation"] { ... } [role="navigation"] > ul { ... } [role="navigation"] > ul > li { ... }

Slide 57

Slide 57 text

The Separation of Concerns [role="navigation"] { ... } [role="navigation"] > ul { ... } [role="navigation"] > ul > li { ... } Ewww! Loading our CSS with DOM information.

Slide 58

Slide 58 text

The Separation of Concerns 


Slide 59

Slide 59 text

The Separation of Concerns 
 
 Semantic concerns.

Slide 60

Slide 60 text

The Separation of Concerns 
 
 Accessibility concerns.

Slide 61

Slide 61 text

The Separation of Concerns 
 
 Stylistic concerns.

Slide 62

Slide 62 text

The Separation of Concerns 
 
 Behavioural concerns.

Slide 63

Slide 63 text

The Separation of Concerns Grid systems are a great example. Handle your layout completely separately to your components. Writing CSS in JS breaks the Separation of Concerns. Can’t reconsider your JS architecture without having to reconsider your CSS architecture.

Slide 64

Slide 64 text

“ The Separation of Concerns If in 14 months you find a new view library or framework you want to try out, you’re out of luck. You will have to invest a lot of time into pulling styles back out of JavaScript modules and into stylesheets again. — keithjgrant.com/posts/against-css-in-js.html

Slide 65

Slide 65 text

Immutability

Slide 66

Slide 66 text

“ Immutability …an immutable object is an object whose state cannot be modified after it is created. — wikipedia.org/wiki/Immutable_object

Slide 67

Slide 67 text

Immutability Provides confidence. Makes things predictable. Helps debugging. Reduces cognitive overhead. Removes caveats, states, and conditions.

Slide 68

Slide 68 text

Immutability .col-6 { width: 50%; }

Slide 69

Slide 69 text

Immutability .col-6 { width: 50%; } @media screen and (max-width: 480px) { .col-6 { float: none; width: 100%; } }

Slide 70

Slide 70 text

Immutability .col-6 { width: 50%; } @media screen and (max-width: 480px) { .col-6 { float: none; width: 100%; } } This has mutated!

Slide 71

Slide 71 text

Immutability .col-6 has one input, but two potential outputs. Outcome depends on how/when you observe it. It has been mutated. Mutable state leads to confusion and unexpected outcomes. Particularly common in CSS.

Slide 72

Slide 72 text

Immutability .col-6 { width: 50%; } @media screen and (max-width: 480px) { .col-6@sm { float: none; width: 100%; } } Use a different class.

Slide 73

Slide 73 text

Immutability .sub-content h2 { text-align: left;
 } .u-text-center { text-align: center; }

...

Slide 74

Slide 74 text

Immutability .sub-content h2 { text-align: left;
 } .u-text-center { text-align: center; }

...

Specificity mismatch. This will be aligned left!

Slide 75

Slide 75 text

Immutability Parts of the codebase are able to mutate other parts. Unpredictable outcomes. Unexpected side effects. This is fixable.

Slide 76

Slide 76 text

Immutability .sub-content h2 { text-align: left;
 } .u-text-center { text-align: center !important; }

...

The only time to use it.

Slide 77

Slide 77 text

Immutability .btn { font-size: 1em; } .promo .btn { font-size: 1.2em; }

Slide 78

Slide 78 text

Immutability .btn { font-size: 1em; } .promo .btn { font-size: 1.2em; } One class, two outcomes.

Slide 79

Slide 79 text

Immutability .btn { font-size: 1em; } .btn--large { font-size: 1.2em; } Two classes, two outcomes.

Slide 80

Slide 80 text

Immutability Don’t have several states of the same thing. Use Modifiers or Responsive Suffixes. Use !important to force immutability. Brings us nicely onto…

Slide 81

Slide 81 text

Cyclomatic Complexity

Slide 82

Slide 82 text

“ Cyclomatic Complexity Cyclomatic complexity is a software metric used to indicate the complexity of a program. It is a quantitative measure of the number of linearly independent paths through a program’s source code. — wikipedia.org/wiki/Cyclomatic_complexity

Slide 83

Slide 83 text

Cyclomatic Complexity M = E - N + 2P Basically just the number of IFs/ELSEs. A form of static analysis. Counting the number of paths through a program. The amount of potential outcomes given certain conditions. Higher complexity is bad: simpler is always better.

Slide 84

Slide 84 text

Cyclomatic Complexity M = E - N + 2P Basically just the number of IFs/ELSEs. A form of static analysis. Counting the number of paths through a program. The amount of potential outcomes given certain conditions. Higher complexity is bad: simpler is always better. Whut?!

Slide 85

Slide 85 text

Cyclomatic Complexity div.main section.content h1 a span {}

Slide 86

Slide 86 text

Cyclomatic Complexity @if div { @if .main { @if section { @if .content { @if h1 { @if a { @if span { // Do stuff. } } } }
 } } }

Slide 87

Slide 87 text

Cyclomatic Complexity div.main section.content h1 a span {} Subject. This is the bit we actually care about.

Slide 88

Slide 88 text

Cyclomatic Complexity div.main section.content h1 a span {} Conditions. All of this is just complexity.

Slide 89

Slide 89 text

Cyclomatic Complexity .text-highlight {} Start off explicitly. Don’t add needless complexity.

Slide 90

Slide 90 text

Cyclomatic Complexity Deeply nested or qualified selectors are bad. They carry a higher Cyclomatic Complexity. Reduce by using much shorter selectors. Get straight to the point. Remove as many conditions and caveats as possible. Start with the correct subject.

Slide 91

Slide 91 text

No content

Slide 92

Slide 92 text

Cyclomatic Complexity div#body section.container section.main div.categories ul li a.product-title {}

Slide 93

Slide 93 text

Cyclomatic Complexity div#body section.container section.main div.categories ul li a.product-title {}

Slide 94

Slide 94 text

The Open/Closed Principle

Slide 95

Slide 95 text

“ The Open/Closed Principle Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification. — wikipedia.org/wiki/Open/closed_principle

Slide 96

Slide 96 text

The Open/Closed Principle Never change anything at its source. Avoid the Domino Effect. Doing so causes visual regressions. Hard to keep track of the knock-on effects. Always make changes via extension (i.e. addition). Possibly the most useful principle for dealing with other peoples’ code.

Slide 97

Slide 97 text

“ The Open/Closed Principle […] once completed, the implementation of a class could only be modified to correct errors; new or changed features would require that a different class be created. That class could reuse coding from the original class through inheritance. — wikipedia.org/wiki/Open/closed_principle

Slide 98

Slide 98 text

The Open/Closed Principle .btn { ... padding: 1em 2em; }

Slide 99

Slide 99 text

The Open/Closed Principle .btn { ... padding: 1em 2em; } Once this is out there, we can’t risk changing it directly.

Slide 100

Slide 100 text

The Open/Closed Principle .btn { ... padding: 1em 2em; } .promo .btn { padding: 1.5em 2.5em; }

Slide 101

Slide 101 text

The Open/Closed Principle .btn { ... padding: 1em 2em; } .promo .btn { padding: 1.5em 2.5em; } Even this is risky as we’re still modifying the base button class.

Slide 102

Slide 102 text

The Open/Closed Principle .btn { ... padding: 1em 2em; } .btn--large { padding: 1.5em 2.5em; } Perfect! A brand new class adds the changes that we want to safely opt in to.

Slide 103

Slide 103 text

The Open/Closed Principle A safe way to make changes. Everything gets opted into explicitly. Prevents changes from happening one-sidedly; the developer has to add the class into the markup as well. A second layer of safety: changes can’t be actioned from one place alone. Build things forward. Analogous to rewriting Git history. Safe way of working with legacy.

Slide 104

Slide 104 text

Orthogonality

Slide 105

Slide 105 text

“ Orthogonality Orthogonality in programming language design is the ability to use various language features in arbitrary combinations with consistent results. — wikipedia.org/wiki/Orthogonality

Slide 106

Slide 106 text

Orthogonality Reduces interdependence. Improves composability. Separates concerns. Reduces collisions. Removes side effects. Good litmus test: can we reorder imports?

Slide 107

Slide 107 text

No content

Slide 108

Slide 108 text

Orthogonality (How well) can we arbitrarily combine things? The implication is that they don’t rely on one another. The hallmarks of a flexible and modular system.

Slide 109

Slide 109 text

Orthogonality Another good test: will it nest? Can things be combined in the DOM? Well-scoped selectors improve orthogonality.

Slide 110

Slide 110 text

No content

Slide 111

Slide 111 text

Collisions!

Slide 112

Slide 112 text

No content

Slide 113

Slide 113 text

Proper scoping provides orthogonality

Slide 114

Slide 114 text

The Moustache Principle

Slide 115

Slide 115 text

“ The Moustache Principle Just because you can, it doesn’t mean that you should. — Harry Roberts

Slide 116

Slide 116 text

No content

Slide 117

Slide 117 text

Thank You Harry Roberts csswizardry.com [email protected] @csswizardry speakerdeck.com/csswizardry