forked from info340/book
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcss-fundamentals.Rmd
361 lines (252 loc) · 22.6 KB
/
css-fundamentals.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
# CSS Fundamentals {#css-fundamentals}
**CSS** (**C**ascading **S**tyle **S**heets) is a declarative language used to alter the appearance or _styling_ of a web page. CSS is used to define a set of formatting **rules**, which the browser applies when it renders your page. Thus CSS can tell the browser to use a particular _font_ for the page text, a certain _color_ for the first paragraph in an article, or a picture for the page's _background_. Files of CSS rules (called **stylesheets**) act kind of like Styles or Themes in PowerPoint, but are way more customizable. You can control nearly every aspect of an element's appearance, including its overall placement on the page.
<p class="alert alert-info">To give you some idea of just how much can be done with CSS, check out the examples in the [CSS Zen Garden](http://www.csszengarden.com/). Every one of those examples uses the exact same HTML content, but they all look completely different because each one uses a different CSS stylesheet.</p>
This chapter will introduce how to include CSS in your web page and the syntax for declaring basic CSS rules. Further CSS syntax, details, and options will be discussed in later chapters.
## Why Two Different Languages?
If you are new to web programming, you might be wondering why there are two different languages: HTML for your page content; and CSS for formatting rules. Why not just include the formatting right in with the content?
There is an old, tried-and-true principle in programming referred to as [**"separation of concerns"**](https://en.wikipedia.org/wiki/Separation_of_concerns). Well-designed software keeps separate things separate, so that it's easy to change one without worrying about the other. And one of the most common forms of separation is to keep the **data** (content) in a program separate from the **presentation** (appearance) of that data.
By separating content (the HTML) from its appearance (the CSS), you get a number of benefits:
- The same content can easily be presented in different ways (like in the CSS Zen Garden). In web development, you could allow the user to choose different "themes" for a site, or you could change the formatting for different audiences (e.g., larger text for vision-impaired users, more compact text for mobile users, or different styles for cultures with different aesthetic sensibilities).
- You can have several HTML pages to all share the same CSS stylesheet, allowing you to change the look of an entire web site by only editing one file. This is an application of the [Don't Repeat Yourself (DRY) principle](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself).
- You can also dynamically adjust the look of your page by applying new style rules to elements in response to user interaction (clicking, hovering, scrolling, etc.), without changing the content.
- Users who don't care about about the visual appearance (e.g., blind users with screen readers, automated web indexers) can more quickly and effectively engage with the content without needing to determine what information is "content" and what is just "aesthetics".
Good programming style in web development thus keeps the **semantics** (HTML) separate from the **appearance** (CSS). Your HTML should only describe the meaning of the content, not what it looks like!
For example, while browsers might normally show `<em>` text as italic, you can use CSS to instead make emphasized text underlined, highlighted, larger, flashing, or with some other appearance. The `<em>` says nothing about the visual appearance, just that the text is emphatic, and it's up to the styling to determine how that emphasis should be conveyed _visually_.
## Including CSS
The best practice for adding CSS styling in your HTML page to create a separate CSS **stylesheet** file to contain the CSS code, and reference that file from your HTML content. These files are named with the **`.css`** extension, and are often put in a `css/` folder in a web page's project directory, as with the following folder structure:
```
my-project/
|-- css/
|-- style.css
|-- index.html
```
`style.css`, `index.css` (the CSS for the `index.html` file), and `main.css` are all common names for the "primary" stylesheet.
You include the stylesheet in your HTML by adding a **`<link>`** element to the page's `<head>` element:
```html
<head>
<!--... other elements here...-->
<link rel="stylesheet" href="css/style.css">
</head>
```
The [**`<link>`**](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link) element represents a connection to another resource. The element includes a **`rel`** attribute indicating the **rel**ation between the resources (e.g., that the linked file is a stylesheet). The `href` attribute should be a _relative path_ from the `.html` file to the `.css` resource. Note also that a `<link>` is an empty element so has no closing tag.
It is both possible and common for a webpage to include _multiple_ stylesheets, each specified with its own `<link>` element in the `<head>`. The stylesheet code will be applied in order: the first linked stylesheet is applied, then the second linked stylesheet, etc..
Note that the `<link>` element is _not_ a hyperlink—it is different from the `<a>` element used to create navigational links! When someone says "add a link to a page", you'll need to determine from context if they mean a hyperlink (`<a>`) or a stylesheet link (`<link>`).
<p class="alert alert-success">If your styling isn't showing up in your page, double-check that the CSS file is linked correctly—especially that you have the correct path to the file!</p>
While using a separate stylesheet is the best practice for keeping your code separated and organized, it is also possible to include CSS code directly in your HTML. You can do this by putting that code inside of a **`<style>`** element (usually inside of the `<head>`):
```html
<head>
<style>
/* CSS code goes here */
</style>
</head>
```
However this means that the CSS styling you write will _only_ apply to that page (it can't be shared across multiple files), and violates the separation of concerns principle. Embedded CSS should only be used for quick experiments.
It is also possible to specify CSS styling for a particular element by giving that element a **`style`** attribute whose value is the list of CSS properties to apply to that element. However, this is less flexible (and more repetitive!) than using separate CSS rules, so is also considered bad practice and should be avoided.
<p class="alert alert-success">Always define CSS code in separate stylesheet files!</p>
## CSS Rules
A CSS stylesheet lists **rules** for formatting particular elements in an HTML page. The basic syntax a CSS rule looks like:
```css
/* This is pseudocode for a CSS rule */
selector {
property: value;
property: value;
}
/* This would be another, second rule */
selector {
property: value;
}
```
A CSS **rule** rule starts with a **selector**, which specifies which elements the rule applies to. The selector is followed by a pair of braces **`{}`**, inside of which is a list of formatting **properties**. Properties are made up of the property _name_ (e.g., `color`), followed by a colon (**`:`**), followed by a _value_ to be assigned to that property (e.g., `purple`). Each name-value pair must end with a semi-colon (**`;`**). If you forget the semi-colon, the browser will likely ignore the property and any subsequent properties—and it does so silently without showing an error in the developer tools!
Like most programming languages, CSS ignores new lines and whitespace. However, most developers will use the formatting shown above, with the brace on the same line as the selector and indented properties.
As a concrete example, the below rule applies to any `h1` elements, and makes them appear in the 'Helvetica' font in white text on a dark gray background:
```css
h1 {
font-family: 'Helvetica';
color: white;
background-color: #333; /* dark gray */
}
```
Note that CSS **comments** are written using the same block-comment syntax used in Java (`/* a comment */`), but _cannot_ be written using inline-comment syntax (`//a comment`).
CSS stylesheet files will often contain dozens, or even hundreds or thousands of rules. Do not attempt to keep the number of rules small; define any rules that you need to in order to achieve your desired appearance!
<p class="alert alert-warning">When you modify a CSS file, you will need to _reload the page in your browser_ to see the changed appearance. Some development servers such as `live-server` may perform this reloading automatically.</p>
### CSS Selector Basics {-}
The first part of the rule is the **selector**. Selectors are used to "select" which HTML elements the CSS rule should apply to. Any element on the page that "matches" what the selector indicates will have the properties of the rule applied to it. This means that each rule can and will style multiple elements on the page!
CSS supports [multiple different types of selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors) (with different syntax for selecting which specific elements to style). This chapter will introduce the two most basic selectors; more options and syntax are discussed in [CSS Selectors](#css-selectors).
The most basic selector, called the **type selector**, selects elements by their type (tag name). For example, the below rule will apply to the all `<p>` elements, regardless of where they appear on the page:
```css
p {
color: purple;
}
```
CSS rules can use the type selector to style any type of element:
```css
/* style all h1 elements to be purple */
h1 {
color: purple;
}
/* style all h2 elements to be gold and italic */
h2 {
color: gold;
font-style: italic;
}
/* style all images to fit within a maximum width */
img {
max-width: 300px;
}
```
It's important to note that that CSS rules will apply to _all_ elements on the page that match the selector. So the above rules will style _all_ `<h1>`, all `<h2>`, and all `<img>` elements regardless of where they are. This means that you can write one rule to style lots of parts of the page—one rule will change all of the `<h1>` headings.
But sometimes you want a rule to apply to only _some_ elements of a particular type—to only some `<p>` or only some `<img>` for example. You will most often make these more limited selections by using a **class selector**. A class selector will select elements with a **`class`** attribute that contains the specified name. For example, if you had HTML:
```html
<!-- HTML -->
<p class="highlighted">This text is highlighted!</p>
<p>This text is not highlighted</p>
```
You could color just the correct paragraph by using the class selector:
```css
/* CSS */
.highlighted {
background-color: yellow;
}
```
Class selectors are written with a single dot (**`.`**) preceding the _name of the class_ (not the name of the tag!) The `.` is only used in the CSS rule, not in the HTML `class` attribute. In the above example, the HTML element has the class `highlighted` (no dot), and the CSS selector uses `.highlighted` to mean "elements with class `highlighted`".
<div class="alert alert-warning">If you try to use a class selector and forget the dot, then the browser will think that you're using an type selector instead—likely selecting an element type that doesn't exist in HTML!
```css
/* Bug: forgot the dot . in the class selector
Instead selects elements of type <highlighted> (do not exist in HTML) */
highlighted {
background-color: yellow;
}
```
</div>
CSS class names should start with a letter, and can contain hyphens, underscores, and numbers. Words are usually written in lowercase and separated by hyphens rather than camelCased or snake_cased. Classes should be given _informative_ names—like you would name a variable! See [Naming CSS Classes](#naming-css-classes) for more details.
Class selectors will apply to any element that contains that class, regardless of the element's type. This can let you apply a single consistent styling to multiple different types of elements:
```html
<h1 class="alert-flashing">I am a flashing alert!</h1>
<p class="alert-flashing">So am I!<p>
```
HTML elements can have **multiple classes**; each class name is separate by a **space** (not a comma):
```html
<p class="alert flashing">I have TWO classes: "alert" and "flashing"</p>
<p class="alert-flashing">I have ONE class: "alert-flashing"</p>
<p class="alert flashing fast">I have THREE classes: "alert", "flashing", and "fast"</p>
```
The class selector will select any element that _contains_ that class in its list. So the first paragraph in the above example would be styled by either the selector `.alert` _or_ the selector `.flashing`. The second paragraph would not be styled by either selector, because `"alert-flashing"` is not the `"alert"` or the `"flashing"` class.
It is common for HTML elements to be given lots of classes, particularly under a _modular class naming_ scheme.
Class selectors are the best way to style a single particular element (just give it a `class` and then write a rule to refer to that), as well as one of the most clearest and effective ways of styling large _portions_ of the page.
### CSS Property Basics {-}
There are [many, many different CSS formatting properties](http://www.w3schools.com/cssref/default.asp) you can use to style HTML elements. All properties are specified using the `name: value;` syntax described above. The task is then to determine which property produces the appearance you want, and provide a valid value for that property. Making beautiful webpages involves combining lots of different properties to style lots of different HTML elements.
<p class="alert alert-success">Pro Tip: modern editors such as VS Code will provide auto-complete suggestions for valid property names and values. Look carefully at those options to discover more!</p>
Discussing every single CSS property is beyond the scope of this book (especially as more are introduced every year!) Later chapters will discuss some common or important properties in more detail. For now, below is a short list of common styling properties you might specify in CSS to get you started:
- [`font-family`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-family): the "font" of the text (e.g., `'Comic Sans'`). Font names containing white space _must_ be put in quotes (single or double), and it's common practice to quote any specific font name as well (e.g., `'Arial'`).
Note that the value for the `font-family` property can also be a _comma-separated list_ of fonts, with the browser picking the first item that is available on that computer:
```css
/* pick Helvetic Nue if exists, else Helvetica, else Arial, else the generic
sans-serif font */
p {
font-family: 'Helvetica Nue', 'Helvetica', 'Arial', sans-serif;
}
```
See [Fonts](#fonts) for more about working with fonts.
- [`font-size`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-size): the size of the text (e.g., `12px` to be 12 pixels tall). The value must include units (so `12px`, not `12`). See [CSS Units](#css-units) for more details on units and sizes.
- [`color`](https://developer.mozilla.org/en-US/docs/Web/CSS/color): text color (e.g., either a [named color](http://www.w3schools.com/colors/colors_names.asp) like `red` or a hex value like `#4b2e83`. See [CSS Colors](#css-colors) for more details on colors in CSS. The [`background-color`](https://developer.mozilla.org/en-US/docs/Web/CSS/background-color) property specifies the background color for the element.
- [`width`](https://developer.mozilla.org/en-US/docs/Web/CSS/width): the width of a block element. The value is usually defined in `px` units (e.g., `300px`). This proeprty can be useful especially for sizing image elements. There is also a similar `height` property.
- [`border`](https://developer.mozilla.org/en-US/docs/Web/CSS/border): a border for the element (see ["Box Model"](box-model)). Note that `border` is a [short-hand property](https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties) which actually sets multiple related properties at once. The value is thus an _ordered_ list of values separated by **spaces**:
```css
/* border-width should be 3px, border-style should be dashed, and border-color
should be red */
p {
border: 3px dashed red;
}
```
Read the documentation for any individual property to determine what values it can take!
<p class="alert alert-warning">Note that not all properties or values will be effectively or correctly supported by all browsers. Be sure and check the browser compatibility listings when using the latest CSS features!</p>
## The Cascade
CSS is called **Cascading** Style Sheets because multiple rules can apply to the same element (in a "cascade" of style!)
CSS rules are _additive_—if multiple rules select the same element, the browser will combine all of the style properties of those rules when rendering the content:
```css
/* CSS */
p { /* applies to all <p> elements */
font-family: 'Helvetica'
}
.alert { /* applies to all elements with class="alert" */
font-size: larger;
}
.success { /* applies to all elements with class="success" */
color: #28a745; /* a pleasant green */
}
```
```html
<!-- HTML -->
<p class="alert success">
This paragraph will be in Helvetica font, a larger font-size, and green color,
because all 3 of the above rules apply to it.
</p>
```
This means you can write one rule that applies to a type of element in general (e.g., "all paragraphs have Helvetica font"), and then write another rule that adjusts or customizes specific elements (e.g., "this one paragraph is (also) green"). Combining rules in this way allows you to make very complex styling out of simple and understandable parts. It also allows you to easily _reuse_ such styling across multiple pages or contexts.
In addition to multiple rules specifying property values for an element, an element can also [**inherit**](https://developer.mozilla.org/en-US/docs/Web/CSS/inheritance) property values from its parent.
```css
/* CSS */
ul { /* applies to all <ul> elements */
font-size: larger;
}
li { /* applies to all <li> elements */
color: red;
}
```
```html
<!-- HTML -->
<ul>
<li>
This element's content will be in a larger font size (inherited from the
parent), as well as red (specified directly).
</li>
<li>(So will this element's content because the same rules apply)</li>
</ul>
```
In the above example, the `<li>` elements will be in a larger font size even though a rule doesn't specifically apply that property to them—the parent `<ul>` element gets that property value, and then the child `<li>` elements inherit it.
Property inheritance means that rules can apply to entire "sections" of the page, and all the content within that section will be styled in the same way. Indeed, you can even use inheritance to apply formatting rules to the _entire page_ by selecting the `<body>` element. (Note that for clarity/speed purposes, you generally do _not_ apply formatting to the `<html>` element).
Note that if a rule explicitly specifies a property's value, that value will be used instead of any inherited value:
```css
/* CSS */
p { /* applies to all <ul> elements */
color: purple;
}
em { /* applies to all <em> elements */
color: gold
}
```
```html
<!-- HTML -->
<p>
This text will be purple <em>(but this text will be gold; it does not
inherit the purple)</em>
</p>
```
<p class="alert alert-warning">Property values can be inherited, but styling _classes_ are not. An element is not considered to have a particular class just because its parent does (though it may inherit the properties that are applied to the parent by having that class).</p>
Because multiple rules may apply to a single element, it's possible that multiple values for the same property will be specified for that element:
```css
/* css */
p { color: blue; }
.alert { color: red; }
```
```html
<!-- html -->
<p class="alert">
This element is styled by both rules, both of change its `color`. The text
will be red, because the `.alert` selector has higher specificity. The `p`
rule's property will be overridden.
</p>
```
If multiple rules try to specify the same property, then the _value from the more **specific** rule is applied_. Class selectors are considered more specific than type selectors, so the rule with the class selector "wins". If two rules are equally specific (e.g., two class selector rules), then the _last declared rule is applied_. See [Selector Specificity](#selector-specificity) for more details. The property value from the less specific rule is said to be **overridden**. Note that property values that don't conflict will still be applied even if one value is overrriden.
The cascade of rules enabled by CSS makes it powerful and expressive, allowing you to write flexible, reuseable rules that can be combined to produce amazing visual appearances. It's like making your own Lego bricks!
That said, the cascade of rules does create a trade-off: you can have lots of reusable rules that apply to multiple elements, but these rules may combine in a scattered way that makes it difficult to intuit about what the page may look like just from considering the code. Having reusable components increases complexity—sometimes too much. Managing this complexity—determining when rules should apply to which elements and when to combine them—is part of the "skill" in working with CSS. Heuristics for designing rules are discussed more in a later chapter; you will also develop a sense for working with CSS as you practice over time.
<p class="alert alert-success">My best advice for managing the large number of CSS rules used in web pages is to follow the [KISS principle](https://en.wikipedia.org/wiki/KISS_principle): _"Keep it simple, silly!"_. CSS rules don't need to be complex; think about rules that apply to general elements or to "sections" of a page. Many elements may only have one or two rules applying to them—and that's okay!</p>
## Resources {-}
Some useful references and documentation for CSS (in general); more specific resources will be included in later chapters.
<div class="list-condensed">
- [CSS Reference (MDN)](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference) a complete alphabetical reference for all CSS concepts.
- [CSS Selectors Reference](http://www.w3schools.com/cssref/css_selectors.asp) a handy table of CSS selectors.
- [CSS Properties Reference](http://www.w3schools.com/cssref/default.asp) a table of CSS properties, organized by category.
- [Getting started with CSS (MDN)](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_started) - an MDN guide for learning CSS
- [CSS-Tricks](https://css-tricks.com/) a blog about tips for using CSS in all kinds of ways. Contains many different useful guides and explanations.
</div>