You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
261 lines
68 KiB
261 lines
68 KiB
import { addBanner, addArticle, addTitle, addHeader, addParagraph, addClassParagraph, addSubHeader, addOrderedList, addUnorderedList, addBlockquote, addInset, addInsetList, addInsetCodeListing, addInsetBulletList, addImageWithCaption, addButtonGroup, addSidebar, addSyntax, menu, global_menu } from '/scripts/import.js'; |
|
import { local_menu } from '/scripts/webdev.js'; |
|
|
|
const heading = document.querySelector(".heading"); |
|
const global = document.querySelector(".global_menu"); |
|
const local = document.querySelector(".local_menu"); |
|
const sidebar = document.querySelector(".sidebar"); |
|
const main = document.querySelector(".main_content"); |
|
|
|
heading.append(addTitle("CSS Essential Training")); |
|
heading.append(addParagraph("Christina Truong - LinkedIn Learning - October 2019")); |
|
heading.append(addTitle("Chapter 2 - Core Concepts")); |
|
|
|
main.append(addSubHeader("CSS Specifications and the W3C")); |
|
main.append(addParagraph("Both the specifications for <a href=\"https://www.w3.org/TR/CSS1/\">CSS1</a> and <a href=\"https://www.w3.org/TR/CSS21/\">CSS2</a> were produced in a single document. With the introduction of <a href=\"https://www.w3.org/Style/CSS/specs.en.html\">CSS3</a>, this has been changed and the specification is now split into individual modules which means that it is much easier, not to mention quicker, to implement incremental changes. If a new module is introduced, it starts at level 1. As of now, there are modules at levels 1 to 4 so it is important to remember that these individual module numbers don't reflect the CSS version number which is still CSS3.")); |
|
main.append(addParagraph("In addition to the official documentation, there are a number of other useful resources such as the <a href=\"https://developer.mozilla.org/en-US/docs/Web/CSS\">Mozilla Developers Network CSS Guide</a> which acts as a reference and a tutorial and has plenty of examples. It is also kept up-to-date which is always important with online documentation but this is probably even more true with CSS, partly because it changes so often, but also because the modular nature of the specifications means that large updates are not so visible. What I mean by this is that modules can be added, removed and updated making CSS very different today than it was, say in 2015 or even earlier.")); |
|
main.append(addParagraph("Bear in mind that CSS1 was introduced in 1996, CSS2 in 1998 and the first drafts of CSS3 appeared in 1999 so CSS3 has been around for over 20 years, but is still CSS3 and may never be replaced by CSS4. This means that you can't really make any assumptions on the version you are looking at based on this. If you are looking at resources relating to CSS3, and this can include books, websites, videos, courses and so on, it is important to check the publication date.")); |
|
main.append(addParagraph("The MDN documentation also provides links to the specifications so it allows you to easily check the 'official' information.")); |
|
main.append(addSubHeader("CSS Values and Units")); |
|
main.append(addParagraph("The units you will use in a CSS rule will vary according to the property and, in general, they are intuitive. For example, a property like color will have a value such as red or a value representing the RGB or HSL numbers. The CSS documentation will provide information relating to the applicable units and the different values you can apply to a property.")); |
|
main.append(addParagraph("You may also see an initial value. This is the value that will apply for a particular property if you don't apply any CSS styles of your own. In other words, this is the browser's default styling and it corresponds to the styles you will see in the rightmost pane of the Developer Options (when it is displaying separate columns for your own CSS and the default CSS.")); |
|
main.append(addParagraph("Some properties take functions as values and those functions may take parameters. For example, the transform property uses the rotate function which takes an argument representing a number of degrees.")); |
|
main.append(addParagraph("Information relating to these values and units can be found in an article in the MDN Web Docs in an article entitled <a href=\"https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Values_and_units\">CSS values and units</a>.")); |
|
main.append(addSubHeader("CSS Syntax and Terminology")); |
|
main.append(addParagraph("The most important principle to follow in terms of syntax (apart from using correct syntax of course) is to be consistent with how you write your CSS. This applies to a number of things, including syntax, but also things like the order of your rules.")); |
|
main.append(addParagraph("For many developers starting out with CSS, it is normal to simply add your CSS rules to a single sheet with new ones going at the end. This has two disadvantages. If there is a conflict, the rule that applies would just be the last one you wrote which may be what you want. The point is that the rules should be applied in the order that you want them to be applied rather than in an order determined by some external factor.")); |
|
main.append(addParagraph("The other disadvantage is that it can make it more difficult to find a particular rule or to work out which rule is going to apply in some circumstances.")); |
|
main.append(addParagraph("Keeping your CSS organised makes it easier to find either a specific rule or rules applying to a specific element and also makes it easier for you to control the order in which those rules are applied.")); |
|
main.append(addParagraph("Something I have mentioned before is the fact that I like to keep CSS rules organised in different style sheets for different purposes. The highest level stylesheets are in a directory called styles and this styles directory is in the site's root directory. Every HTML page links to that stylesheet, so that's where I put the styles that are going to apply to the whole site. Sometimes, this means separating rules for a selector so that the general rules go into that stylesheet. For example, if you look at the top of this page, you will see that I have styled the course title so that it stands out - it has a font-size of 48 pixels, top and right margin of 0 so that the background colour is flush with the edges of the viewport (except the bottom edge, obviously) and some padding to move the text slightly away from the border.")); |
|
main.append(addParagraph("I want all course titles, regardless of subject group, to look like this so these rules go in the site wide stylesheet like this.")); |
|
main.append(addInsetCodeListing([".coursetitle {", " font-size: 48px;", " padding: 22px 10px;", " margin: 0px;", "}"])); |
|
main.append(addParagraph("The colours used in the course title, the color and background-color properties follow a kind of theme where I have one pair of colours for web development pages, another for Linux pages and so on, so these colour go into a stylesheet that is only accessed by a subject group. So, alongside the styles folder in the root directory, I have a folders called webdevelopment, linux and a few others. Each of these folders also contains a folder called styles, with a stylesheet called styles.css in that (I think of these as subject stylesheets). Each HTML page within one of these folders links to its subject stylesheet. Since the styles here are only applied to a single subject group, this allows me to set a colour scheme that is only applied to a particular subject. As an example, in my webdevelopment stylesheet, the styles which determine the background colour and font colour for the main part of the viewport are")); |
|
main.append(addInsetCodeListing(["body {", " background-color: #9BB7D4;", " color: #0072B5;", "}"])); |
|
main.append(addParagraph("Note that this is using an type selector of body and that means it will affect everything inside the viewport unless overridden. This is actually the first rule in my stylesheet which means that any other rule I create for either property will override the body rule because it is obviously coming later, and that includes the rule that sets the colours for the course title.")); |
|
main.append(addInsetCodeListing([".coursetitle {", " background-color: #0072B5;", " color: #9BB7D4;", "}"])); |
|
main.append(addParagraph("To demonstrate this, I have created a page called sample1.html which follows the same basic layout as other pages in this course. It has it's own copy of the webdevelopment stylesheet and it is linking to this rather than the original. The only change to the CSS is that the rules governing the font-color of the course title have been moved to the top and are now above the rules for the body and we can see the effect this has by looking at <a href=\"samples/sample1.html\" target=\"_blank\">sample1.html</a> (opens in a new tab). Perhaps surprisingly, there is no change to the colour scheme. For this page, the rules relating to body comes after the rules relating to the course title, but they use an type selector. A type selector will target any element with a matching tag (in this case, <body>). The rules relating to course title use a class selector. In this example, it is targeting an element with a <h2> tag, but only those with a class of \"coursetitle\" so it is actually more specific than the rules targeting the body. That's why changing their relative position in the CSS file did not affect which rule applied.")); |
|
main.append(addParagraph("Now, the file sample2.html is identical to sample1.html and has the same CSS stylesheet, with the exception that the CSS rules relating to course title have been modified to target an element, <h2> instead. I did cheat a little by copying the rules for font-size, but we can see how this change affects the page by looking at <a href=\"samples/sample2.html\" target=\"_blank\">sample2.html</a> (opens in a new tab).")); |
|
main.append(addParagraph("Since both sets of rules now use a type selector, neither is more specific than the other and the conflict is resolved according to the order in which they are applied with the last rule being applied. This makes sense if you think about it. As the browser parses the CSS, the first declaration block it finds (a declaration block being a set of rules enclosed by a pair of curly braces, usually applying to a single selector, but they can be applied to a comma separated list of selectors if they are all using the same rules) should be applied to <h2> elements and sets their properties, including the color and background-color properties. It then finds the declaration block for the <body> element and sets the background-color and color properties for all elements, including <h2> so that determines the colours displayed when the page is viewed.")); |
|
main.append(addParagraph("Within each page, I always add the link to the site wide styles before the link to the subject styles. This means that if there is some property I want to apply site wide, this can go in the site stylesheet, but I still have the option of overriding this in the subject stylesheet knowing that the styles will be applied after the styles in the site wide sheet. This means that I can use the subject styles to override the 'global' styles without having to think about it.")); |
|
main.append(addParagraph("It's important to remember that the CSS is arranged in a specific way on this site because that makes sense for this particular site. Depending on your project, a single stylesheet or a single location for your stylesheets may make more sense. In short, the question of which arrangement is better is far less important than the question of which arrangement is better for my project. As you use CSS more, you may well encounter problems which could have been solved by arranging your CSS better but that sort of experience will inevitable lead you to be a better developer so it's not a bad experience. For more information on how to style your code, there is an interesting article on <a href=\"https://codeguide.co/\">codeguide.co</a>.")); |
|
main.append(addSubHeader("The Color and Property Values")); |
|
main.append(addParagraph("There are a number of ways to specify a colour value as I mentioned earlier. You can use the colour name, RGB values or HSL values. In my experience, the values I tend to use are either the colour names or an RGB value expressed as a 6 digit hexadecimal number. Both of these present their own problems.")); |
|
main.append(addSubHeader("Colour names")); |
|
main.append(addParagraph("The obvious complication here is what colour names are recognised by CSS. There are obvious values such as red, blue, black, white and so on and these are considered to be basic colours. There are other colours and these are all listed on the W3.org site under <a href=\"https://www.w3.org/wiki/CSS/Properties/color/keywords\">CSS/Properties/color/keywords</a> which lists both basic and extended colours. The extended colours includes values such as lightred, darkred and so on and also some less obvious values such as antiquewhite or lemonchiffon.")); |
|
main.append(addSubHeader("RGB")); |
|
main.append(addParagraph("The site mentioned lists both the hex and decimal values for each colour listed by keyword but this amounts to a very small number of the colours you can specify with RGB. A better option might be an RGB color picker and there is an example of this on the <a href=\"https://www.w3schools.com/colors/colors_mixer.asp\">w3schools.com</a> website which generally provide a swatch of some kind that allows you to visually select the exact colour you want and provides the appropriate RGB Values.")); |
|
main.append(addParagraph("The w3schools.com website actually provides a lot of really useful information relating to colours and colour schemes. I have found that a really useful page when defining the colour scheme for this site has been a page showing the <a href=\"https://www.w3schools.com/colors/colors_2021.asp\">'hottest' colours of 2021</a> and there are similar pages for previous years going back as far as 2016.")); |
|
main.append(addSubHeader("Type and Universal Selectors")); |
|
main.append(addParagraph("We have already seen plenty of examples of type selectors. A type selector targets any element with a particular type such as <p> or <h2> and this is a very general selector in the sense that it will select anything just based on the type of the HTML tag, regardless of whether it has a class attribute. It is almost the least specific type of selector, the only exception that I am aware of being the universal selector (*) which will select all elements regardless of type. For example, if we had the rule")); |
|
main.append(addInsetCodeListing(["* {", " color: red;", "}"])); |
|
main.append(addParagraph("this will set the font colour to red for any element that can accept this as an attribute. If we have another rule, it doesn't matter whether it is in the same stylesheet, of")); |
|
main.append(addInsetCodeListing(["p {", " color: blue;", "}"])); |
|
main.append(addParagraph("This is more specific since it only targets a single type. Let's assume that he have one or more paragraphs with class \"different\" and we have the rule")); |
|
main.append(addInsetCodeListing([".different {", " color: black;", "}"])); |
|
main.append(addParagraph("To keep things simple, let's assume all of these rules are in the same stylesheet and that the stylesheet is linked to the page with the HTML we are interested in. We have three rules which could set the colour of any given paragraph. The least specific is the universal selector since it targets everything and this sets the colour for our paragraphs to red. The second rule is more specific since it only targets paragraphs so it overrides the first rule, for paragraphs only, and sets the colour to blue.")); |
|
main.append(addParagraph("The third rule also only targets paragraphs, but only those with a class attribute set to \"different\". In theory, it is possible that every <p> element has a class of \"different\" which would be kind of redundant since the type selector, p, and the class selector, .different, would both be targeting exactly the same elements. The class selector is still more specific than the type selector because it can select certain paragraphs and ignore others.")); |
|
main.append(addParagraph("The overall effect of these three rules is that all paragraphs with a class of \"different\" will be black and all other paragraphs will be blue. No paragraphs will be red because the p selector sets the colour for blue for all paragraphs and only the more specific rule with the class selector can overrule this.")); |
|
main.append(addParagraph("Note that since we are talking about selectors with a clear order from most to least specific, the order in which they are applied does not matter. This also applies when the rules are in different stylesheets.")); |
|
main.append(addParagraph("As a matter of interest, the course demonstrates these selectors on <a href=\"https://codepen.io/christinatruong/pen/NJjQXy?editors=1100\"></a>codepen.io")); |
|
main.append(addParagraph("The CSS for this is")); |
|
main.append(addInsetCodeListing(["* {", " color: red;", "}", "", "h1 {", " color: blue;", "}", "", "h2 {", " color: pink;", "}"])); |
|
main.append(addParagraph("If you go into codepen, you should see that the text in the viewport turns red when you type in the first rule. When you type in the second rule, the main heading turns blue and when you type the third rule, the sub-headings turn pink.")); |
|
main.append(addSubHeader("Class and ID Selectors")); |
|
main.append(addParagraph("I spoke earlier about the use of class and id selectors and the difference between then and I use class selectors quite a lot in the CSS for this site. I don't think that I am currently using any id selectors.")); |
|
main.append(addParagraph("For any given element, you can only one have one class selector, but you can apply more than one class and you would do that by putting the list of class names in quotes with a space between each like this")); |
|
main.append(addSyntax("<p class=\"fancy intro\">Fancy intro paragraph.</p>")); |
|
main.append(addParagraph("This gives us a paragraph which we can select with two different class selectors, .fancy or .intro. We can also create CSS rules that only apply when an element has both class values. To do this, we specify both class selectors with a space between them like this")); |
|
main.append(addInsetCodeListing([".fancy.intro {", " color: goldenrod;", "}"])); |
|
main.append(addParagraph("Other than the fact that they must be unique and the selector begins with a #, id selectors are similar to class selectors. Personally, I don't use them very much as a CSS selector, but they can also be used for in-page links (things like a button or link you click to go back to the top of the page or to a specific point in the page. This is achieved by using the id as a href value like this.")); |
|
main.append(addSyntax("<a href=\"#top\">")); |
|
main.append(addParagraph("You can also use them with links to a specific point in a different page by adding the id to the end of the usual href value like this.")); |
|
main.append(addSyntax("<a href=\"https://www.w3.org/TR/selectors-3/#id-selectors\">")); |
|
main.append(addParagraph("You can follow that link by clicking <a href=\"https://www.w3.org/TR/selectors-3/#id-selectors\">here</a> (opens in a new tab). The link takes us to the current documentation for CSS selectors and the id takes us to the part of that page dealing with id selectors. If you view this page, you will see that there is a list of contents on the left hand side. This is quite common where a page contains the amount of information that this page does and the contents panel uses in-page links so that we can easily find the information we need without having to scroll all the way down to the appropriate section.")); |
|
main.append(addParagraph("Whether you are using classes or selectors, it is very important to use meaningful names because you may need to read and understand both your HTML and CSS at a later date.")); |
|
main.append(addSubHeader("Class and ID Selector Exercise")); |
|
main.append(addParagraph("For this exercise, we will use the same pen mentioned earlier. We will start by adding a class to the first <h2> element, we'll use the name example. We will use a class selector to target it and change its colour to orange.")); |
|
main.append(addInsetCodeListing([".example {", " color: orange;", "}"])); |
|
main.append(addParagraph("We can use the same class name with other elements. This may mean other <h2> elements or any other element. We will demonstrate by adding the class to the <h1> element and we see that it also changes colour to orange. The interesting thing here is that we have changed the appearance of the page by amending the HTML rather than the CSS. The change does come from the CSS, but we have already attributed some styles to the class example, so we can also apply these style (in this example it is just one property) by changing the class of an element.")); |
|
main.append(addParagraph("Next, we're going to add a second class to the first <h2> element, we'll call this example2. We will use this as a class selector to change the background colour to black.")); |
|
main.append(addInsetCodeListing([".example2 {", " background-color: black;", "}"])); |
|
main.append(addParagraph("The fact that the element has two class names is not important here. What matters is that one of those class names matches the selector and so the CSS rule is applied to it.")); |
|
main.append(addParagraph("If we want to apply a particular style only to an element with that has both these class names, we use both in the selector without a space between them. For instance, let's set the font-size to 50 pixels.")); |
|
main.append(addInsetCodeListing([".example1.example2 {", " font-size: 50px;", "}"])); |
|
main.append(addParagraph("Finally, we will add an id to the <h1> element and we will call it example. Class and id are separate attributes, so we can use the same for both. Normally, we wouldn't do that because it could be confusing, but it is certainly possible. We will use an id selector to set the font-size for the <h1> element to 100 pixels.")); |
|
main.append(addInsetCodeListing(["{", " font-size: 100px;", "}"])); |
|
main.append(addParagraph("Unlike classes, an HTML element cannot have more than one id so there is no syntax to apply a style to an element that has two ids.")); |
|
main.append(addParagraph("For reference, the final code for both the HTML and CSS for this exercise is as follows.")); |
|
main.append(addSubHeader("HTML")); |
|
main.append(addInsetCodeListing(["<h1 class=\"example\" id=\"example\">Heading</h1>", "<h2 class=\"example example2\">Sub-heading</h2>", "<p>Paragraph with text. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Assumenda dignissimos quisquam sequi, est eligendi reiciendis?</p>", "<h2>Sub-heading</h2>", "<p>Another paragraph with text. Nulla qui aperiam, cumque labore, repudiandae quae accusantium quos possimus illo, odit numquam, eveniet doloremque!</p>"])); |
|
main.append(addSubHeader("CSS")); |
|
main.append(addInsetCodeListing(["* {", " color: red;", "}", "", "h1 {"," color: blue;", "}", "", "h2 {", " color: pink;", "}", "", ".example {", " color: orange;", "}", "", ".example2 {", " background-color: black;", "}", "", ".example.example2 {", " font-size: 50px;", "}", "", "#example {", " font-size: 100px;", "}"])); |
|
main.append(addSubHeader("Descendant Selectors")); |
|
main.append(addParagraph("We can use descendant selectors to target certain elements in a similar way to using a class selector. However, where a class selector targets all elements with a specified class, the descendant selector targets certain elements depending on where they are in relation to other elements. Consider the following snippet of HTML.")); |
|
main.append(addInsetCodeListing(["<section>", " <p>This is a paragraph with a <a href=\"#\">link</a> inside it.</p>", " <p>This is just a paragraph.</p>", " <a href=\"#\">This is just a link</a>", "</section>", "<a href=\"#\">This is another link</a>"])); |
|
main.append(addParagraph("We have a <section> tag which contains two paragraphs and two links and one of the links is inside the first paragraph. We have another link after the section and you can see this HTML by clicking <a href=\"samples/descendant.html\" target=\"_blank\">here</a> (opens in a new tab). There is no CSS applied to this page. You may recall that we are using a CSS reset for this site, but that reset is applied through one of the CSS stylesheets so in this case, we are not even loading in the reset so the browser defaults will apply.")); |
|
main.append(addParagraph("Remember, we can use a type selector of a to target all links. Let's say that we only want to target the links inside the section. We do that with a descendant selector where we are specifying only a elements that are descendants of section elements, descendant being a reference to the DOM and essentially meaning that the link is nested inside section. The selector for this is")); |
|
main.append(addInsetCodeListing(["section a {", " /* styles go here */", "}"])); |
|
main.append(addParagraph("This will select both of the links inside section and it doesn't matter that one of these links is further nested inside a paragraph. We could add the paragraph as a second ancestor.")); |
|
main.append(addInsetCodeListing(["section p a {", " /* styles go here */", "}"])); |
|
main.append(addParagraph("In this case, we are selecting only links that are inside a paragraph that is inside a section. So this would target the first link, but not the second.")); |
|
main.append(addParagraph("In these examples, we have only used type selectors, but we can also use class or id selectors. For example, let's say that our section has an id of main-content. We could target all links inside this section with")); |
|
main.append(addInsetCodeListing(["#main-content a {", " /* styles go here */", "}"])); |
|
main.append(addParagraph("Similarly, let's say that all of the paragraphs inside the section have a class of section-paragraph. We could target all links within a paragraph with that class that are also within section with")); |
|
main.append(addInsetCodeListing(["section .section-parapgraph a {", " /* styles go here */", "}"])); |
|
main.append(addParagraph("or")); |
|
main.append(addInsetCodeListing(["#main-content .section-parapgraph a {", " /* styles go here */", "}"])); |
|
main.append(addParagraph("if we want to use the id selector for section.")); |
|
main.append(addParagraph("Let's try that out by adding a few CSS rules. We will start by setting the colour for all links to black.")); |
|
main.append(addInsetCodeListing(["a {", " color: black;", "}"])); |
|
main.append(addParagraph("You can try this in <a href=\"https://codepen.io/christinatruong/pen/KEyzNo?editors=1100\">codepen</a> as well and we will see the colour of all of the links changes to black.")); |
|
main.append(addParagraph("Now, let's apply another rule to set the colour of all of the links inside section to green.")); |
|
main.append(addInsetCodeListing(["section a {", " color: green;", "}"])); |
|
main.append(addParagraph("This changes the colour of the first two links, but the third link is outside of the section so it is not targeted by this rule.")); |
|
main.append(addParagraph("In this example, section doesn't have a class or an id so we will give it a class of container and then use the class to target the links inside section.")); |
|
main.append(addInsetCodeListing([".content a {", " color: orange;", "}"])); |
|
main.append(addParagraph("This is more or less the same as the previous rule, we are just using a different way to target section so the result is the same, both of the links inside section are now orange and the other link is unchanged. It is important to note that these last two rules are equivalent to each other because we only have one section and it has a class of content. If we had several sections, but only one with class content, the first rule would target all section elements, the second would only target the section with class content. So they are equivalent rules here, but it certainly is not the case that a class and a type are interchangeable in this context.")); |
|
main.append(addParagraph("Next, we will use types to target the link inside the paragraph in section.")); |
|
main.append(addInsetCodeListing(["section p a {", " color: pink;", "}"])); |
|
main.append(addParagraph("When we look at the page, you might expect that one of the links will now be pink, but this rule has no effect. This is because a class selector will always be more specific than a type selector and so this rule is ignored. Quite simply, you cannot override a rule by adding a less specific rule which is actually what we did here.")); |
|
main.append(addParagraph("Let's try that one again, but we will use the class content rather than the type section.")); |
|
main.append(addInsetCodeListing([".content p a {", " color: pink;", "}"])); |
|
main.append(addParagraph("This time the link inside the paragraph inside the section does turn pink. Now, we used two rules with the class selector")); |
|
main.append(addInsetCodeListing([".content a {", " color: orange;", "}"])); |
|
main.append(addParagraph("and")); |
|
main.append(addInsetCodeListing([".content p a {", " color: pink;", "}"])); |
|
main.append(addParagraph("The second of these seems to be more specific because it uses a second type selector. However, this rule is applied last so that may be the reason for it being applied. In order to confirm that this rule is more specific, I will put the rule without the p selector at the end of the CSS. This means that the link inside the paragraph will only be pink if this rule is more specific (actually, I used hotpink rath than just pink which is too similar to orange to be able to see clearly that it is pink. The html page with all of these CSS rules applied can be viewed by clicking <a>here</a> and this opens in a new tab. As expected, the first link is now pink which shows that")); |
|
main.append(addSyntax(".content p a")); |
|
main.append(addParagraph("is more specific than")); |
|
main.append(addSyntax(".content a")); |
|
main.append(addParagraph("which I guess most people would have expected.")); |
|
main.append(addSubHeader("Grouping Selectors")); |
|
main.append(addParagraph("Grouping selectors is just a way to target different elements with a single declaration block. For instance, if you need to set the font colour for all <h1>, <h2> and <h3> elements to blue, you can do that with")); |
|
main.append(addInsetCodeListing(["h1, h2, h3 {", " color: blue;", "}"])); |
|
main.append(addParagraph("This is just a short hand version of")); |
|
main.append(addInsetCodeListing(["h1 {", " color: blue;", "}", "", "h2 {", " color: blue;", "}", "", "h3 {", " color: blue;", "}"])); |
|
main.append(addParagraph("In this example, the selectors are all type selectors but you can include any selectors as long as they are separated by commas. Let's say that your <h1> have a class value of main-heading, we can also write this as")); |
|
main.append(addInsetCodeListing([".section h2, h3 {", " color: blue;", "}"])); |
|
main.append(addParagraph("Each selector that is separated by a comma in this way is completely independent of the others and you may need to be careful of this when using descendant selectors. For example, let's say you have the following.")); |
|
main.append(addInsetCodeListing(["section h1, h2 {", " color: green;", "}"])); |
|
main.append(addParagraph("This will target any <h1> element that is nested inside a <section> div and any <h2> element. It doesn't matter, in this case, whether the <h2> element is inside a <section> div or not. If your intention is only to target either of these elements inside a <section> div, you will need to specify both descendant selectors in full, so")); |
|
main.append(addInsetCodeListing(["section h1, section h2 {", " color: green;", "}"])); |
|
main.append(addParagraph("The main reason for grouping selectors is for efficiency of writing (since you have to write common rules less often) and you can more easily change the rule for all these elements (assuming you still want them all to be set to the same colour).")); |
|
main.append(addParagraph("You also have the advantage of greater efficiency of reading since there are fewer rules to read through and it is easier to see when different elements are being styled with the same rule. As an example, let's say we have applied the style shown above where all <h1>, <h2> and <h3> elements are all set to the same colour. When you are reading the CSS, you can quite easily see that the same colour has been specified for all three, bearing in mind that the rule may have been overridden with another rule. If you didn't group the selectors, you would have to find each selector separately to confirm what rule has been applied. Of course, a simpler way to see what rules have been applied may be to simply view the webpage, but there may be times when this is insufficient.")); |
|
main.append(addParagraph("For example, you may have overridden some rule such as colour using a class or id selector and you need to check what colour, if any, has been set as the default (that is, for elements that don't have that class or id).")); |
|
main.append(addParagraph("We also saw an example of something similar where we were combining selectors like this")); |
|
main.append(addInsetCodeListing([".fancy.intro {", " color: blue;", "}"])); |
|
main.append(addParagraph("There is no comma or space between the two because this style is not being applied to elements targeted by either selector, it will only apply to elements targeted by both selectors. In this case, these are both classes, but we can combine a class and a type selector. Let's say we have a paragraph with class \"intro\" and we want to target all elements where the type is p and class is intro, we would do that with")); |
|
main.append(addInsetCodeListing(["p.intro {", " color: blue;", "}"])); |
|
main.append(addParagraph("You may wonder if it is possible to combine type selectors in this way, and it should be fairly obvious why this is not the case. Class is an attribute and a single element can have more than one class value. Type is itself an element, for instance, type p corresponds to a <p> element and so an element cannot have more than one type. You can nest one element inside another and you may have a piece of text that is nested like this")); |
|
main.append(addSyntax("<div><p>This text is inside a paragraph inside a div</p></div>")); |
|
main.append(addParagraph("but these are still distinct elements. You can still target this element based on the fact that is inside both a p and div type element, but you would do that with a descendant selector rather than combining them.")); |
|
main.append(addSubHeader("Inheritance and Specificity")); |
|
main.append(addParagraph("HTML elements can inherit some CSS styles from a descendant and this can greatly simplify styling. For example, let's say that you want to set the font colour for a page to white and the background colour to black. You could do that by setting the styles for each element type independently. However, all of the visible elements are contained within the <body> tag. If you set your CSS styles using the body selector")); |
|
main.append(addInsetCodeListing(["body {", " background-color: black;", " color: white;", "}"])); |
|
main.append(addParagraph("Every element on the page will have these styles applied to them unless overridden. So, you can set these colours for the page and then change the colours for any elements you want to be an exception to these rules. You can also do a similar thing with any element that contains other elements. This means that you can set certain styles for the whole page or a section of the page as well as for individual elements. There is a full list of properties which shows, amongst other things, the properties that are inherited in this way on the <a href=\"https://www.w3.org/TR/CSS21/propidx.html\">w3.org</a> website.")); |
|
main.append(addParagraph("We've already looked at specificity, but we will go into how this is calculated here. As a general rule of thumb, the selector types from the least specific to the most specific is as follows.")); |
|
main.append(addInsetList(["Universal (*)", "Type (p)", "Class (.class)", "ID (#id)"])); |
|
main.append(addParagraph("It's easy to make a comparison between rules that use a single selector by simply comparing them, but as we have seen, selectors can be combined and this makes the situation a little more complex. We can take a look at how these rules work in <a href=\"https://codepen.io/christinatruong/pen/YgaBgb?editors=1100\">this example</a> on codepen. The HTML for this example is")); |
|
main.append(addInsetCodeListing(["<section>", " <p id=\"example\" class=\"example\">A paragraph.</p>", "</section>"])); |
|
main.append(addParagraph("This is pretty simple, we have a <p> element inside a <section> element. The <section> element has a class attribute and an id attribute, both of which have a value of example. We also have some CSS.")); |
|
main.append(addInsetCodeListing(["section {", " font-family: avenir, sans-serif;", " font-size: 30px;", " color: orange;", "}", "", "* {", " /* color: lightblue; */", "}", "", "p {", " /* color: green; */", "}", "", ".example {", " /* color: black; */", "}", "", "#example {", " /* color: purple; */", "}", "", "section p {", " /* color: lightgreen; */", "}"])); |
|
main.append(addParagraph("You will notice that most of these rules are commented out so that as it is, only the rules at the top which are being applied using a type selector of section is taking effect, so the text is orange.")); |
|
main.append(addParagraph("You can also see this page by clicking <a href=\"samples/specificity.html\">here</a> (opens in a new tab).")); |
|
main.append(addParagraph("The next rule uses the universal selector. The universal selector is the least specific selector, so you might expect that there is nothing that it can override since by definition, everything else must be more specific, right? This is generally true, but there is one exception. It can override an inheritance selector. The first selector, section, does not specifically target a <p> element. It just targets any element that happens to be a descendant of the section type selector. The universal selector is equivalent to taking all the type selectors on your page and combining them as a group of selectors. In our sample page, we could have written the rule as")); |
|
main.append(addInsetCodeListing(["h1, section, p {", " color: lightblue;", "}"])); |
|
main.append(addParagraph("This probably makes it a little clearer and helps to explain why the universal selector can override inherited styles. This means that when we enable this rule by removing the comment characters, the text becomes light blue.")); |
|
main.append(addParagraph("Next, we have a rule that uses a p selector so this must be at least as specific as the universal selector. If we enable this rule, we see that the text does turn green. If you are experimenting with this yourself, I recommend uncommenting the rule first to see what effect that has and then moving it to the end of the CSS file to see if that has any effect. This will let you know whether the p selector has overridden the universal selector because it is more specific or because of the order in which the rules are being applied. In this case, the order doesn't have any effect, so we can say that a particular type selector does override the universal selector.")); |
|
main.append(addParagraph("The next two rules uses the class selector and then the id selector. There is a clear order of specificity here so we can see that each rule is applied as it is enabled but there is no need to change the order of the rules since it is clear which of the rules is most specific. We can see that enabling the rule with a class selector changes the colour to black and the rule with the id selector changes it to purple.")); |
|
main.append(addParagraph("The final rule targets a <p> element inside a <section> element. Clearly this will not be more specific than either a class or id selector so we shouldn't see any change in the colour and that is the case.")); |
|
main.append(addParagraph("I will comment out the rules with the id selector and the class selector and now the text does change to light green. I am fairly certain that this selector, which targets a <p> element inside a <section> element will be more specific than a selector that only specifies a single element type. In other words, I would expect that the section p selector is more specific than the p selector, but because of the order in which the rules are applied, it is still possible that they have the same specificity.")); |
|
main.append(addParagraph("To test my theory, I will move the p selector to the end of the CSS and I expect that the colour of the text will not change and that is the case, so we can see that the descendant selector is more specific than a single type selector.")); |
|
main.append(addParagraph("When it comes to specificity, the number of selectors is significant and this is why the section p selector overrides the p selector. We can calculate this using numeric values for each type of selector.")); |
|
main.append(addInsetBulletList(["The universal selector has a value of 0", "A type selector has a value of 1", "A class selector has a value of 10", "An id selector has a value of 100"])); |
|
main.append(addParagraph("In theory, this means a single id selector can be overridden by a combination of class and type selectors and a single class selector can be overridden by a number of type selectors. However, since the value of an id is ten times greater than that of a class selector and this is ten times greater than the value of a type selector, this is not likely to happen. Any combined selector that uses more than three or four individual selectors is probably a good indicator that your HTML code is way too complex so in practical terms, these calculations are only likely to be useful when comparing similar selectors such as the example above were two type selectors overrides a single type selector.")); |
|
main.append(addParagraph("If you are in doubt about which rule will take precedence, there are two ways to resolve this. The first is to simply try it and see which rule takes effect. The second is to either perform a manual calculation to see if this explains which rule takes effect, or you can use an online <a href=\"https://specificity.keegan.st/\">Specificity Calculator</a>, such as this one by Keegan Street. You may need to adapt either your CSS to make a rule more specific or to change the order in which they apply so that the rule that is applied is the one that you want and you may also need to add a class or an id to your HTML code in order to facilitate that.")); |
|
main.append(addSubHeader("The Cascade and Importance")); |
|
main.append(addParagraph("I talked a little about the order of the rules and how this can affect how they are applied. We have seen that the a selector that is more specific will take precedence over a selector that is less specific where they are both targeting the same element. If they have the same level of specificity, then the order in which they are applied determines which rule takes precedence.")); |
|
main.append(addParagraph("There are two factors in determining the order in which the rules are applied. The first is the order in which the stylesheets are loaded. As an example, consider the stylesheets attached to this page.")); |
|
main.append(addInsetBulletList(["<link href=\"/styles/styles.css\" rel=\"stylesheet\" type=\"text/css\">", "<link href=\"/webdevelopment/styles/styles.css\" rel=\"stylesheet\" type=\"text/css\">"])); |
|
main.append(addParagraph("To put these into context, the styles in the first of these are intended to be applied to all of the pages on this site, whereas the styles in the second stylesheet are only intended to be applied to pages relating to Web Development. As an example, let's say that I want all of the text inside a paragraph to be 14 pixels and I want it to be blue on pages relating to Web Development. The font-size goes in the first stylesheet, and the colour goes in the second. I do try to avoid conflicts by not specifying the same rule twice so in that sense, the order of the stylesheets may not be important. However, if I decide that I want the font-size to be 14 pixels for all pages except pages relating to Web Development, let's say I want to change this to 12 pixels, I can do that by overriding the font-size in the web development stylesheet.")); |
|
main.append(addParagraph("For this reason, the order of the stylesheets is important because by applying the more general stylesheet first, I know that where there is a conflict, it is the style I have defined for web development pages that is going to be applied. So this gives me better control of how those styles are applied.")); |
|
main.append(addParagraph("The second factor relates to how styles in the same stylesheet are applied. When the stylesheet is read in, the styles are read from top to bottom so if two selectors targeting the same element have the same specificity, the one that appears later in the stylesheet will be applied.")); |
|
main.append(addParagraph("This also applies if there is a conflict within a declaration block. Consider the following example.")); |
|
main.append(addInsetCodeListing(["p {", " color: purple;", " background-color: pink;", " font-size: 14px;", " font-size: 16px;", "}"])); |
|
main.append(addParagraph("In this example, we have specified the same rule regarding font-size twice and the second one takes precedence, simply because it comes after the first one within this declaration block. You may realise that there is no way that the first of the two could ever apply so there is no reason to apply the same rule twice. But if your CSS becomes complicated enough and you have a lot of rules in a single block, it is possible that you may have two rules for the same property so this is something to bear in mind if you are seeing the wrong rule being applied.")); |
|
main.append(addParagraph("If you find that a particular rule is not being applied and you really can't figure out why, you can add the important keyword to the end of a rule like this")); |
|
main.append(addInsetCodeListing(["p {", " font-size: 12px!important;", "}"])); |
|
main.append(addParagraph("Adding the important keyword means that this will override any other rule regardless of specificity or order. In fact, the only way you can override a rule which has this keyword is to apply it to another rule which would have taken precedence if you hadn't applied it. In short, if there is a conflict between rules and they both have the important keyword, the normal rules of specificity and order would apply.")); |
|
main.append(addParagraph("Important is really a last resort and is a poor substitute for properly planning and organising your CSS, but it is important to know that it exists, if only so that you will recognise it if you see it in somebody else's code. There may be a few cases where it is useful to use important and you can read about that in the <a href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity\">MDN Docs</a>.")); |
|
main.append(addSubHeader("Project: Adding Colours")); |
|
main.append(addParagraph("In the course video, I noticed that Christina has a block comment at the start of her CSS file with the colour palette for the page. This is a really useful technique which I've started to do as well because it's handy to have a list of colours to be used in that file, especially if it is a coherent palette, by which I mean the colours go quite well together. She seems to have generated this on the <a href=\"https://coolors.co/\">coolors.co</a> website which is another useful resource. It allows you to generate random colour palettes and lock any colours you like so that you are only shown colours that match with it. The site also has some trending palettes if you need some inspiration.")); |
|
main.append(addParagraph("Christina also likes to group her CSS according to which section of the page is being styled. This isn't really something that would work well on this site, for example, since the page is not quite split into sections in the same way that the resume is, although I do have a header section, a main section and a footer section. In any case, I will use the same technique for this exercise and we will start by setting the colours.")); |
|
main.append(addParagraph("We will start by setting a global text colour for the page, for which we will use dark gray - almost black from our palette. We will apply this to the <body> and this is the most general tag, we will put this at the top of the CSS in the global styles section.")); |
|
main.append(addInsetCodeListing(["body {", " color: #343434;", "}"])); |
|
main.append(addParagraph("Next, we will add our background colours for each section. We will start with the header section, and since we only have one <header> element on the page we can just use a simple type selector for this and we will set the background to dark blue in the profile section.")); |
|
main.append(addInsetCodeListing(["header {", " background-color: darkblue;", "}"])); |
|
main.append(addParagraph("This gives us something of a class since we now have dark text on a dark background, but we are just going to worry about the background colours initially and we can modify the text colours later.")); |
|
main.append(addParagraph("Before we add any CSS, we will add the comments dividing the file into sections, simply because it is easier to do that while the file is more or less empty and it gives us a guide when adding the CSS rules to make sure we put it in the right place.")); |
|
main.append(addParagraph("The dividing comments use a long string of hyphens so that it has more visual impact and better separates the sections, like this.")); |
|
main.append(addSyntax("/* Global styles")); |
|
main.append(addSyntax(" ------------------------------------*/")); |
|
main.append(addParagraph("We will also add similar sections for the profile section, projects, work experience, education and contact information.")); |
|
main.append(addParagraph("For the next three sections, projects work experience and education, each section is inside a <section> element so we can't use the type selector. This can mean having to edit the HTML code so that it gives you an alternative selector, but we don't have to do that here because the different sections also have class names we can use. For projects, the class is projects so we can use that as the selector and we will set the background colour to almost white.")); |
|
main.append(addInsetCodeListing([".projects {", " background: #F7FFF7;", "}"])); |
|
main.append(addParagraph("We can similarly use the work-experience class to set the background in that section to light blue. We won't add a background colour to the education section because that is going to be styled differently. The contact info is in the footer and since there is only one footer on the page, we can use the type selector, footer, and we will set the background colour to dark gray - almost black.")); |
|
main.append(addParagraph("Now, we can save everything and check out how the resume looks now. We did expect to see a couple of problems with dark text against a dark background and we can see that in both the header and footer sections, so we will change the text colour using the color property to almost white.")); |
|
main.append(addParagraph("As a quick aside, you may have noticed that Christina uses the background property rather than background-color. I wasn't aware that background on its own was a valid property so I had to look that up and I found that it is actually a shorthand. For the background, there are a number of properties you can set individually and background-color us one of those. This shorthand version allows you to set them all in a single declaration, much as the padding shorthand allows you to set the padding for top, right, bottom and left in one line. For reference, you can read up on the background property in the <a href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/background\">MDN Docs</a>.")); |
|
main.append(addSubHeader("Pseudo-Class Selectors and Links")); |
|
main.append(addParagraph("A pseudo-class is not explicitly declared in your HTML, but is a class that is automatically associated with an interactive element in the page. For example, let's say you have a link on your page. A user can interact with the link by clicking on it, but there are other actions they can perform such as hovering over it with the mouse. There are a lot of these pseudo-classes, but in this section, we will only look at those which can be associated with a link and they are")); |
|
main.append(addInsetList([":link", ":visited", ":hover", ":active", ":focus"])); |
|
main.append(addParagraph("Most of us will be aware of the default styling for links which are blue if the user hasn't visited the link or purple if they have. If we want to change the default, we can do that with the :link pseudo-class.")); |
|
main.append(addParagraph("To demonstrate this, I have a page called links.html which you can visit by clicking <a href=\"samples/links.html\" target=\"_blank\">here</a> (this opens the page in a new tab). There are several links on the page and no styling so everything looks like you would normally see in a browser using default styles and this includes the links. Initially, they will be blue and they are blank links so clicking on one of them will not take you anywhere. However, it will change the link colour to blue since clicking on them is the action required to visit the link.")); |
|
main.append(addParagraph("You might be surprised to see that they all change colour to purple, regardless of which link is clicked. This is because they all have the same href value as shown below.")); |
|
main.append(addInsetList(["<a href=\"#\">Link 1</a>", "<a href=\"#\">Link 2</a>", "<a href=\"#\">Link 3</a>", "<a href=\"#\">Link 4</a>"])); |
|
main.append(addParagraph("Essentially, this means that they are all the same link and so on by visiting on one link, you are actually visiting them all.")); |
|
main.append(addParagraph("It is worth noting that if you style your links using the pseudo-class, which would look something like this")); |
|
main.append(addInsetCodeListing([".linuxlink:link {", " color: #ffd100;", "}"])); |
|
main.append(addParagraph("This is actually from my Linux styles. I wanted to change the colours for links because they clashed with the dark background colour I am using. Note that I am using a class name and this is because I only want to style links appearing with a dark background. This applies to all of the links except those on the Linux subject page, so it may have been easier to set a class for those so I could change them to something different, but I actually prefer this approach which means I am changing the styles on just the links that I want to style rather than changing them on everything and then having to change some back.")); |
|
main.append(addParagraph("It is also worth noting that this method will not style all elements with an anchor tag and class linuxlink, it will only style a link that has a href value. Instead of using either a class like this, you can use a type selector of a and this will target all anchor tags, whether they have a href value or not. To demonstrate this, we have an anchor tag in the test html page (samples/links.html) that doesn't have an href value and we will style these links with like this.")); |
|
main.append(addInsetCodeListing(["a:link {", " color: green;", "}", "", "a:visited {", " color: orange;", "}"])); |
|
main.append(addParagraph("I have made a couple of modifications to the HTML, removing the # sign from the href value for link1, so it now has an empty value and giving a href value to link2 that links back to the page it is on. Hopefully, this will allow me to click the link and see it change colour without leaving the page. So now, if we look at <a href=\"samples/links.html\">samples/links.html</a> (opens in a new tab) and we can see that the links are green, but become orange when visited. The anchor tag without a reference is not styled either with the default CSS for a link or with the styles in links.css, but the link with an empty string as the href value is.")); |
|
main.append(addParagraph("Both the :link and :visited pseudo-classes are only applicable to links, but there are others which apply to both links and other types of elements. One of these is :focus.")); |
|
main.append(addParagraph("I have added this to the CSS rules in links.css.")); |
|
main.append(addInsetCodeListing(["a:focus {", " color: red;", "}"])); |
|
main.append(addParagraph("If we open the page again, we can see that the links turn red (mostly) when they come into focus and this can happen if you click the link or press the tab key repeatedly until the focus is on a link. If you click link2, this is reloading the page so you may see it briefly turn red and then back to orange as the page reloads and the focus returns to the default (whatever is in focus when the page initially loads). The same thing happens if you click on link1, the link with an empty string in href.")); |
|
main.append(addParagraph("Similarly, we can use the pseudo-class :hover to change the appearance when you hover over a link. For instance")); |
|
main.append(addInsetCodeListing(["a:hover {", " background: gray;", "}"])); |
|
main.append(addParagraph("If we open up the page again, we can see the background for the links change to grey as we hover over them.")); |
|
main.append(addParagraph("The last pseudo-class we will look at here is active. An element is active when you click on it and it remains active until you release the mouse-button.")); |
|
main.append(addInsetCodeListing(["a:active {", " color: white;", "}"])); |
|
main.append(addParagraph("In the links.html page, we can still see the grey background when we hover over a link and it turns white when we click on it. If you do a single click without holding the mouse button, you will see a very quick flash of white, but the link remains white when you hold the mouse button down.")); |
|
main.append(addParagraph("Like :focus, both :hover and :active can apply to other elements. You may notice, for example, that they apply to all anchor tags, whether the tag has an href value or not so you will see that 'link' with a grey background when you hover over it and it turns white when clicked. However, because there is no href value, it can't be brought into focus so you won't see it turn red.")); |
|
main.append(addParagraph("Also, you should bear in mind that in some cases, the browser may have a default setting that prevents you from using these classes. For example, when using Firefox on a Mac, you may find that the hover feature is disabled and you may need to switch it on and you can get some information on doing this <a href=\"https://stackoverflow.com/questions/11704828/how-to-allow-keyboard-focus-of-links-in-firefox\">here</a>.")); |
|
main.append(addSubHeader("Project: Styling Links")); |
|
main.append(addParagraph("for this part of the project, we are going to style the links on the resume. We will start with a general style for all links, so this will go in the global section in our CSS file.")); |
|
main.append(addInsetCodeListing(["a {", " color: #FFE66D;", "}", "", "a:hover {", " text-decoration: none;", "}"])); |
|
main.append(addParagraph("Notice that we have used a as the selector rather than a:link. It is not very common to use anchor tags without an href value so in most cases, it won't matter which you use. We have set the colour for the links to yellow and styled them so that the underline on the links disappears when you hover over it. We haven't set any style for a visited link since we don't really need to be able to see which links have been visited here.")); |
|
main.append(addParagraph("This gives us a bit of a problem with the links in the project section which are hard to read. Rather than change them to a dark colour, which would be the obvious solution, we will give them a dark background with a light colour, so that will give us a kind of button effect. In order to target the links in the projects section, we will use a descendant selector and we will use the almost white colour for the text against a dark blue background. We will also remove the underline from these links (this is being completely removed rather than being styled so that it disappear when a user hovers over the link, so we haven’t used the :hover pseudo-class).")); |
|
main.append(addInsetCodeListing([".projects a {", " color: #F7FFF7;", " background: #2F3061;", " text-decoration: none;", "}"])); |
|
main.append(addParagraph("The links look okay now but we want to enhance the button-like appearance by adding 8 pixels of padding all around and by rounding the corners with the border-radius property which we will set to 4 pixels. This really makes the links look like buttons, although arguably, the downside of this is that they don't really look like links and so, in spite of the fact that a user might intuitively expect a button to be clickable, it's always possible that they might not realise that these are links. This is just a personal opinion on my part, but I do like the appearance and I actually may consider restyling the links on the home page and subject pages for this site in a similar way.")); |
|
main.append(addParagraph("The other thing to be careful with is that if you have a block of text with a link somewhere inside it, which we don't have in the resume, but there are a few examples on this page, you may need to be careful about adding a property like padding because it is going to raise the height of the while line of text. If this isn't a in line on its own or in the first line of a paragraph, you will see some odd spacing.")); |
|
main.append(addParagraph("We want to also add a hover feature to these links, which may be useful because it will help to emphasise the fact that they are clickable. We won't change the colour though. Rather, we want to change the opacity of the background colour. To do this, we will need the functional values of the RGB colour (that is, the distinct RGB values in decimal), currently we are using the hex value. The easiest way to convert it is to use an online converter such as the one at <a href=\"https://www.webfx.com/web-design/hex-to-rgb/\">webfx.com</a>.")); |
|
main.append(addParagraph("To start with, we will get the hex value for our dark blue colour and put that into the converter at webfx.com and this will give us the value of 47, 48, 97. This is just converting each pair of digits in the hex value into a decimal value so it would be simple enough to do with a calculator.")); |
|
main.append(addParagraph("To add this to the CSS, remember that we only want it to apply to links in the projects section so we will use the same descendant selector we saw earlier with the pseudo-class.")); |
|
main.append(addInsetCodeListing([".projects a:hover {", " background: rgba(47, 48, 97, 0.8);", "}"])); |
|
main.append(addParagraph("We are going to use the rgba keyword to signify that this is an RGB value with the additional alpha value of 0.5 which will give us 80% opacity when a user hovers over one of these links (you can also specify the opacity as a percentage so")); |
|
main.append(addInsetCodeListing([".projects a:hover {", " background: rgba(47, 48, 97, 80%);", "}"])); |
|
main.append(addParagraph("works just as well.")); |
|
main.append(addParagraph("Going back to the point I made about links inside a paragraph, I didn't notice but there is a link near the bottom of the projects section which falls in to this category. It doesn't look too bad in my browser, but we will look at how we can fix this anyway. To do this, we are going to create a new selector just for the links we want to display these button like qualities and we will call it btn.")); |
|
main.append(addParagraph("In the CSS, we will change the selectors from .projects a to .project .btn and from .projects a:hover to .projects .btn:hover, so rather than selecting all of the anchor tags in the projects section, we are now targeting all of the elements in the projects section that have the class, btn. Actually, we could now dispense with .projects from the selector since it is only links within that section that we will give the class to.")); |
|
main.append(addParagraph("Leaving this in means that we have the opportunity to create more elements with class btn and style them differently if they aren't in the projects section. This is my personal opinion again, but I don't really like this idea. I would rather give the elements a more meaningful name like project-btn. If you have two sections, let's say projects and contact info, and you want both of these sections to have links styled like buttons, but you want to style them independently of each other - it could be argued that these should be considered separate classes and therefore given distinct names such as projects-btn and contact-btn.")); |
|
main.append(addParagraph("Conversely, if you use a more generic class like btn, and you apply it to links in both sections, this does allow you the freedom to apply common styles globally and specific styles using the descendant selector.")); |
|
main.append(addParagraph("As an example, let's say that you have a link in the contact info section and you want to give it the same sort of button styling, but with different colours. We could give both sets of buttons a different class name and then apply the styles we want to each. If we give them the same class name, this allows us to apply common styles to all of these button links, perhaps in the global section of the stylesheet - so that would include the padding and the rounded corners. This, of course, means using the class .btn as our selector.")); |
|
main.append(addParagraph("We can then apply the differentiated styles using the descendant selector - either .projects .btn or footer .btn. This is similar to the concept of inheritance in object-oriented programming where you create a generic, perhaps abstract class that contains the attributes or properties common to the whole class and then create subclasses to contain the information that is more specific.")); |
|
main.append(addParagraph("I would say that either approach is acceptable if you are certain that you are only going to use the class in one section. However, if you want to create variations on it, depending on how much of the data is going to be common to all button links, you may decide that having a global class to style the common attributes and specific classes for the specific attributes (in this example, the more specific attributes are the colours) is probably a better idea. And bear in mind that if you do use a generic class, even if you don't have button links in other sections, it is much easier to add these later since you can just add a class of btn which will automatically add the styles you have created for all buttons and then use a descendant selector for the colours or whatever specific attributes you need.")); |
|
main.append(addParagraph("All in all, I may well have changed my mind about Christina's approach, but I do think that if you are using a generic class like btn, you should put that in the global section of your CSS so that you have more flexibility to add button links to other sections later. It seems to me that she is using the first approach where there is no class to hold the common attributes, so really we have a syntax that would lend itself to creating more buttons, but applying all of the styles using a single selector removes all of those advantages.")); |
|
main.append(addParagraph("In any case, if look at the page again, we will see that the styling has been removed from all of the links, although we do still have the styling in the global section where the colour was set to yellow and so on so our links will revert to this yellow colour.")); |
|
main.append(addParagraph("In the HTML, we will locate the links that should have this button styling and then add the btn class as an attribute and then we will see that the links that we want to look like buttons, do look like buttons.")); |
|
main.append(addParagraph("So this means that some of our links now have the problem of using a light colour against a light background, so we will need to go and style these again. In our CSS, we will use our original selector which was .projects a and use that to set the colour attribute to dark blue. This is going to apply the dark blue colour to all anchor tags in the projects section, but this will be overridden by the selector with the .btn class since this is a more specific selector. We can now go back to our page by clicking <a href=\"resumes/resume4.html\">here</a> and we will see that the links we want to have the button appearance do, and the other links have that darker colour that works better with a light background.")); |
|
|
|
addSidebar("webdev"); |