-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcss_notes.Rmd
More file actions
438 lines (305 loc) · 22.3 KB
/
css_notes.Rmd
File metadata and controls
438 lines (305 loc) · 22.3 KB
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
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
---
title: "Introduction to Cascading Style Sheets"
author: "Rose McKeon"
date: "(June 12th 2019)"
output:
html_document:
toc: true
toc_depth: 2
toc_float: true
collapsed: true
smooth_scroll: true
number_sections: true
css: css/css_notes.css
---
<div class="alert alert-info" role="alert">
**After reading through `css_slides.pdf` and working through these notes, you will have been introduced to the basics of cascading style sheets (CSS) and you should be able to start styling Hyper Text Markup Language (HTML) pages with CSS.**
Please think of this document as a living document, which you are free to improve (like a [wiki](https://en.wikipedia.org/wiki/Wiki)) with minor edits, new sections that others might find useful, or additional resources that you find that you think others might also find useful.
</div>
***
# Loading CSS in a HTML page
## Internal styles
You can define style rules by adding a **style** element inside the **head** element of a webpage.
> Open `/html/example.html` in a browser to view the rendered page and take a look at how a HTML page looks when it has absolutely no styling loaded.
> Now, open the same file in a text editor (RStudio will do!) to see the HTML code that makes the page.
> Have a go at putting the **style** element below in the right place, near the very top of the document, between the opening `<head>` and closing `</head>` tags. Try not to disrupt any other elements that are nested in the head by making sure your style element sits one level deep inside the head.
```html
<style type="text/css">
/* It contains a CSS declaration block that targets paragraphs. */
p {
font-size: 1.2em;
line-height: 1.4;
}
</style>
```
You should end up with the start of the document looking like this:
```html
<!DOCTYPE html>
<html>
<head>
<title>Make me Pretty</title>
<!-- HINT: Put your <style></style> and <link /> tags here -->
<style type="text/css">
/* It contains a CSS declaration block that targets paragraphs. */
p {
font-size: 1.2em;
line-height: 1.4;
}
</style>
</head>
<body>
```
> **Save the document and refresh the page in your browser.** You should see all the text get bigger and the line spacing increase. Did you notice that the final paragraph didn't change?
That's because it has an inline style added as a *style* attribute to that paragraph.
## Inline styles
> While you're viewing the rendered page in your browser, try right clicking on that last paragraph and choosing **Inspect** from the menu. Can you see the inline style?
You should be able to see a panel that shows you the markup of the whole page on the left, with the last paragraph highlighted `<p style="font-size: .7em">` and the CSS styles that apply to it on the right. The style we just added will appear at the top, but it's crossed out because it can't be loaded.
> On the right hand side of this console, try unticking the **element.style** `font-size: 0.7em` to see what the page would look like without the inline style.
<div class="alert alert-warning">
**Remember** how to use this console to inspect elements and thier CSS - it's a really useful way to test things out without actually making changes to your code.
</div>
The **style** attribute can be used to set CSS properties directly on HTML elements. Inline styles cannot be overridden easily. They're generally best avoided as they start to rui the spearation between structure and style, but they do have their uses. CSS declarations are added to the **style attribute** in the HTML markup of the element you want to style. Each declaration is separated by semi-colons like this: `style="property: value; property: value"`.
> Try adding the inline style `style="text-align: center"` to the **header** element of our example page (his element is right near the top of the body).
You should end up with a header that looks like this:
```html
<header style="text-align: center">
<h1>Very basic HTML page</h1>
<blockquote>Full of nonsense no less.</blockquote>
</header>
```
## External styles
It's often better to keep your stylesheet in a separate file. External stylesheets can be loaded with a webpage by adding the **link** element inside the **head** element, and setting particular attributes.
> Make a new text file and save it in `/css` with the extension `.css`. Add the declaration block below to the new file.
```css
body {
font-family: sans-serif;
}
```
> Now let's tell our page how to use it. Add the following **link** element, again between the opening `<head>` and closing `</head>` tags, without disrupting any other elements in the head, by making sure it sits one level deep.
```html
<link href="../css/your-styles.css" rel="stylesheet" />
```
> Remember to change the **href** attribute so the path goes to the file you created.
Your head should end up looking something like this:
```html
<!DOCTYPE html>
<html>
<head>
<title>Make me Pretty</title>
<!-- HINT: Put your <style></style> and <link /> tags here -->
<style type="text/css">
/* It contains a CSS declaration block that targets paragraphs. */
p {
font-size: 1.2em;
line-height: 1.4;
}
</style>
<link href="../css/your-styles.css" rel="stylesheet" />
</head>
<body>
```
It doesn't matter, at the moment, if you put the `<link>` tag before or after the **style** element. But, DON'T put it *between* the opening `<style>` and closing `</style>` tags. Only CSS can go here.
# Properties
Properties are specific names for all the styles that you can control. We've already used a few like `font-size`, `font-family` and `text-align`. Properties are like parameters of functions, in that they have to be spelt correctly and they can only take particular types of information. Property names are always followed by a colon, a space, and then a value, followed by a semicolon. `property: value;` It's good practice to put every property indented on it's own line, so they are easy to read and comment out.
**There are tons of properties you can set with CSS, for a full list see [here](https://www.w3schools.com/cssref/default.asp)**.
> Let's try some of the options in your new stylesheet. Look up **background-colour**, **background-image**, **background-repeat**, **background-position**, and **background-size**. Now, try writing a background style for the body element (don't worry about if the text is still readable just now).
It could look something like this:
```css
body {
background-image: url("https://jooinn.com/images/abstract-background-1.jpg");
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
}
```
> Try out some different values for these properties to see what they do.
# Selectors
Selectors are what you use to target HTML elements, they define which parts of the page your properties will be applied to. We've been using them already to target things like paragraphs, headers and body elements. Selectors come *before* the curly braces that contain the declaration block. You need atleast one, but you can also have multiple, comma spearated, selectors:
```css
/* like this */
h1, h2 {
text-transform: uppercase;
}
/* OR like this with line breaks */
h1,
h2 {
text-transform: uppercase;
}
```
All the tags that are used to define HTML elements can be used as selectors. You can also select targets using **class** or **ID** names that elements have been given as well as a variety of other advanced methods. Any declaration block will affect ALL elements of the type defined by it's selector.
> Let's make all the text more readable by targeting the element **main**. Add the declaration block below to your new stylesheet. then inspect the element and turn the styles on and off to see what they do.
```css
main {
background-color: black; /* fallback */
background-color: rgba(0, 0, 0, .7);
color: white;
max-width: 700px;
margin: 0 auto;
padding: 1em 2em;
border-radius: 2em;
}
```
> Did you wonder why there are two declarations for **background-color**? Not all browsers accept `rgba` values (with opacity) so adding a fallback declaration *before* it makes sure there is still a compatible style. Any declaration that follows another gets loaded last and takes priority, if it can be used.
## Classes
A **class** is a type of HTML attribute used to give elements custom names.
```html
<p class="big"></p>
```
Classes are intended to be used many times, perhaps even across different elements. So the properties they contain should make sense relative to the name, and they should work in a range of situations.
**Classes are used as selectors like this:**
```css
.big {
font-size: 2em;
}
```
**Classes are the prefferred way to target elements** as they allow for changes to the HTML markup, without affecting the rendering of the page. In this example we could change the markup to `<span class="big"></span>` and our style would still be applied, because it targets the class and not the element.
> There is a **div** element with the class **special** in the the example page already `<div class="special">`. Try writing a declaration block that will make this section stand out from the rest of the page. It could look something like this:
```css
.special {
background-color: white;
color: #4f4f4f;
padding: 0 2em 2em;
}
.special h2 {
background-color: #815AA6;
color: white;
padding: .5em 1em;
border-top-right-radius: 1em;
border-bottom-right-radius: 1em;
display: inline-block;
position: relative;
left: -2em;
}
```
Spaces between selectors are used to target nested elements. The selector `.special h2` in this example targets all **h2** elements that are *inside* elements which have the class **special**.
You can keep going too, with as many spaces as you like for deeply nested elements, but using the shortest selectors possible is recommended for speed and readability.
> Now try changing the **div** element to a **section** element instead (this tag is more descriptive). Remember to change both the opening and closing tags.
Your HTML should end up looking like this:
```html
<section class="special">
<!-- all the headings and paragraphs inside it... -->
</section>
```
> Now refresh the page and *nothing* should change.
Your `.special` class style declaration will still work because we didn't target the element by it's tag.
### Combining class and element selectors
You can combine class selectors with element selectors like this too: `div.special`. The `.` that prefixes the class selector acts to concatenate the two selectors together. This targets all **div** elements with the class **special**. Targeting elements in this way removes the benefits of using class names (now you can't change divs to sections without updating the CSS too). Only use selectors like this if you absolutely have to; it can be useful when you need to override a style that already specifies the element.
You can also concatenate as many classes as you want, so you can imagine a selector that looks something like this: `.special.sale` or `.special.info`.
> What do you think the markup for these elements would look like?
These selectors target elements that have multiple classes. By using spaces as separators in the attribute you can add as many classes to an element as you like: `class="special sale whatever blah blaaaah"`. So, the selectors `.special.sale` and `.special.info` target elements that look like this:
```html
<section class="special sale">
<!-- some special offer here -->
</section>
<section class="special info">
<!-- some special information here -->
</section>
```
All the elements with class **special** will use the same set of declarations but then the extra classes **sale** and **info** differentiate them. Taking this approach helps you to write less repetitive CSS.
> Copy the whole chunk of markup between `<section class="special">` and `</section>`. Paste it just above the `<footer>` to create another special section. Give this new section another class; call it whatever you like, so your class attribute ends up looking something like: `class="special whatever"`.
I've said call it 'whatever you like' but there are some rules to class names:
- They can't have sapces.
- They can't start with a number.
- Be consistent with any other formatting you choose to use. For example, make them always lowercase with hyphens for spaces to conform to popular standards.
> Now, try adding a new declaration block that changes a property for this new section and makes it a little different than the other one (HINT: target the new class in your stylesheet).
## IDs
An **id** is a another type of HTML attribute used to give elements custom names. It works in a very similar way to classes. However, IDs are intended to be used only once in a page, so they are usually very specific.
**IDs are used as selectors like this:**
```html
<body id="something-particular"></body>
```
```css
#something-particular {
/* some very particular properties */
}
```
IDs are often used on body tags so that you can write styles that are specific to particular pages. You can combine ID selectors in all the same ways as classes. So, selectors with IDs in might start to look like: `section#important`, `#about .special h2`, or `#signup.special` etc. IDs are also especially easy to target with javaScript and, because they're not intended to be repeated, make these scripts highly selective.
All the same naming rules for classes apply to IDs too.
> Try adding an ID to an element along with a style declaration that targets it in your stylesheet.
# Overriding styles
<div class="alert alert-warning" role="alert">
**Ordering is really important.**
</div>
We've already seen how ordering property declarations within declaration blocks can be important for setting colour fallbacks. The ordering of the entire stylesheet is important too. Whatever styles are written first, at the top of your stylesheet, will be loaded first. If another declaration block later on targets the same element with a different style, that later style will override the earlier one. If different properties are set in the later declaration block then all the outcome will be a combination of both sets of rules.
## Loading order
The order of styles loaded in different ways is important too. Remember how we couldn't override the inline paragraph style with our internal style?
If you load multiple external styles, the last one loaded will override all the others. Internal styles can be loaded before or after external styles, depending on where the `<link>` and `<style>` tags are placed.
Inline styles, are an exception to this rule. They're not loaded last but they're automatically considered more important, so they stop other styles from overriding them.
> Try loading the readymade external stylesheet `/css/example.css` in the example webpage.
You can use the **link** element again like this:
```html
<link rel="stylesheet" href="../css/example.css" />
```
Everything we've done together, plus a few extra styles is in this sheet. So when you save and refresh you should see some changes.
> How has the font-size declaration for the footer in my example stylesheet taken priority over the inline style we looked at earlier?
If you inspect the paragraph, you should see that the style I've included has a special statement after the value for font-size: `!important`. Whatever order other styles are loaded in after this declaration, nothing will be able to override it unless it too uses the `!important` statement. **Don't use these unless you absolutely have to** (it's bad practice and very annoying to edit later).
> Play with the order of styles, putting them before and after each other. Inspect elements to see what happens and get a feel for which styles override each other.
# RMarkdown
You can load external styles with Pandoc for you RMarkdown documents really easily. Just include the **css** option as part of the **html_document** statement in your Pandoc header, with the path to your file:
```Rmd
output:
html_document:
css: your-stylesheet.css
```
> Take a look at the header of the file that I used to generate these notes (`css_notes.Rmd`). Find out what external stylesheet is being used and take a look at it to see what custom styles this page uses.
> Try adding a declaration block of your own to this stylesheet. See if you can change the colour or the font or the headings (re-knit the Rmd document and refresh the page to see your changes).
# Bootstrap
Twitter's [Bootstrap](https://getbootstrap.com/) is an extremeley popular grid framework which provides hundreds of styles and complimentary javascript libraries to web developers. Around 18% of all websites make use of it to underpin their layouts and custom styles ([Burge 2018](https://www.ostraining.com/blog/webdesign/bootstrap-popular/)).
**This is also the grid framework that Knitr and Shiny use in their generated HTML pages.** So, by getting familiar with Bootstrap's built in styles you can save youself time and effort when customising styles of knitted HTML documents, or Shiny apps; apply tons of pre-exisiting styles, just by adding the right class names to HTML elements.
- Imagine you have a list
- But you want to highlight one point <span class="label label-default">this one!</span>
- So it stands out from the rest.
These labels have classes which are already defined by Bootstrap, along with other colours too:
<span class="label label-default">Default</span> <span class="label label-primary">Primary</span> <span class="label label-warning">Warning</span> <span class="label label-danger">Danger</span> <span class="label label-success">Success</span>
```html
<span class="label label-default">Default</span>
<span class="label label-primary">Primary</span>
<span class="label label-warning">Warning</span>
<span class="label label-danger">Danger</span>
<span class="label label-success">Success</span>
```
<div class="alert alert-info" role="alert">
<div class="row">
<div class="col-lg-8">
This is just one small example. Bootstrap has LOADS of components and styles you can make use of, like this info alert box, link buttons, icons, menu navigation, tabbed content, and best of all, the grid framework for positioning things. The grid is customisable across different devices as all the classes have a size component like `sm`, `md` or `lg`. So on a small screen this alert is full width, but on a big screen it's split into two columns, and I didn't have to code any of the CSS that controls that myself.
</div>
<div class="col-lg-4">
<a href="https://getbootstrap.com/docs/3.3/" class="btn btn-primary btn-lg">Go See! <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span></a>
</div>
</div>
</div>
Watch out for the Bootstrap version being used. None of the R stuff I've looked at uses the latest releases so the best Bootstrap features are often missing. Most use v3.3 last time I checked, so I've linked to those docs above.
> Try out some Bootstrap elements: Have a go at putting a new alert box in this document by editing `css_notes.Rmd` and using the markup below to wrap a paragraph.
```html
<div class="alert alert-danger">
Whatever paragraph text here...
</div>
```
> Knit the page to see your changes. The paragraph you wrapped should now be in pale red box with rounded corners.
# Useful Resources {.lead}
- [W3Schools CSS](https://www.w3schools.com/css/): Free interactive online lessons.
- [W3Schools HTML](https://www.w3schools.com/html/default.asp): Free interactive online lessons.
- [CSS Tricks](https://css-tricks.com/snippets/css/): Very cool snippets, techniques and demos.
- [Positioning](https://css-tricks.com/almanac/properties/p/position/): How to position elements with CSS like a pro.
- [Bootstrap](https://getbootstrap.com/docs/3.3/): Grid framework used by Knitr and Shiny.
- [RMarkdown HTML Style](https://bookdown.org/yihui/rmarkdown/html-document.html#appearance-and-style): Styling documentation.
- [HTML5 Boilerplate](https://github.com/h5bp/html5-boilerplate): Best practice bare bones HTML page template.
- [ColorZilla](https://www.colorzilla.com/): Colour picker browser extension.
- [Colors](https://coolors.co/3772ff-f038ff-ef709d-e2ef70-70e4ef): Colour palette generator (makes sure your colours always compliment each other).
- [CSS matic](https://www.cssmatic.com/): CSS generators for fancy background gradients, textures and shadows.
# Advanced Topics
> Topics for another day if any of you get really involved.
## Complex selectors
There are more complex ways to target elements. You can target every other row of a table, for example, or just the 4th element of every list. You can even use selectors to only target links that open in new tabs. Or, to specify a style that only effects the 2nd level of 3 nested lists. You can also target *states* like `:hover` and `:focus` which are used all the time for link and button styles.
## Animation and Transformations
CSS can even be used to animate, rotate and skew elements. Fading colour changes on hover is a common use example of this, but you can also do far more complex animations.
## Browser compatability
For some properties (usually more advanced CSS3 ones) you'll have to set a range of slightly different properties in your declaration block to get them to work consistently in different browsers. Something like this:
```css
box-shadow: 10px 10px 5px 0px black; /* Standard CSS */
-webkit-box-shadow: 10px 10px 5px 0px black; /* Chrome and Safari */
-moz-box-shadow: 10px 10px 5px 0px black; /* Firefox */
```
Sometimes styles, especially layout ones, have unexpected outcomes in different browsers too (usually Internet Explorer). There are ways to set conditional styles so that different browsers load different CSS.
## Compilers
If you ever have to write a lot of CSS, consider learning how to write [Sass](https://sass-lang.com/) or [less](http://lesscss.org/). These languages have a syntax almost identical to CSS, but with additional shorthand, nesting, and global variables. Command line compilers check your code for errors and turn it into CSS, ensuring consistent syntax and allowing you to easily change variables like colours, that might be repeated hundreds of times. Some packages can even add all the browser specific CSS properties for you automatically. Additionally, they can minify the stylesheet that is loaded on your website for increased speed, while keeping your development code easily readable. Your development code can even be split up into numerous files, and you can define which files become part of the compiled CSS.