About this ebook
CSS has grown from a language for formatting documents into a robust languagefor designing web applications. Its simplicity is deceptive, however. It belies the complexity of the box model, stacking contexts, specificity, and the cascade. CSS mastery lies in understanding these concepts and how to take advantage of them.
This book will show you how to write better, more efficient CSS, and to use the plethora of the new cutting-edge CSS features available to the front-end developer. You'll also learn to master tools that will improve your workflow.
- Organize your CSS to create efficient, reusable, and maintainable code
- Discover complex layout techniques: grid layouts, multi-column layouts, and more
- Use advanced effects: transitions, transforms, filter effect, and animations
- Re-use and dynamically control CSS values with custom properties
- Combine CSS and SVG to create seriously powerful graphics
This edition has been thoroughly updated to cover newer CSS features and techniques, including new chapters on visual effects and managing document scroll.
Tiffany B Brown
Tiffany B. Brown is a freelance web developer and technical writer based in Los Angeles. She has worked on the web for more than a decade at a mix of media companies and agencies. Before founding her consultancy, Webinista, Inc., she was part of the Opera Software Developer Relations & Tools team. Now she offers web development and consulting services to agencies and small design teams.
Related to CSS Master
Related ebooks
Responsive Web Design with HTML5 and CSS3 Rating: 4 out of 5 stars4/5A Pocket Guide to CSS Animations Rating: 5 out of 5 stars5/5Modern JavaScript Applications Rating: 0 out of 5 stars0 ratingsThe CSS Guide: The Complete Guide to Modern CSS Rating: 5 out of 5 stars5/5CSS3 Foundations Rating: 4 out of 5 stars4/510 Lessons in Front-end Rating: 2 out of 5 stars2/5HTML5 and CSS3 All-in-One For Dummies Rating: 0 out of 5 stars0 ratingsBeginner CSS: Like Putting Lipstick on a Zombie: Undead Institute, #2 Rating: 0 out of 5 stars0 ratingsProfessional CSS3 Rating: 5 out of 5 stars5/5Getting SASSY: A Practical Guide to SASS Rating: 0 out of 5 stars0 ratingsResponsive Web Design with HTML5 and CSS3 - Second Edition Rating: 4 out of 5 stars4/5Mastering JavaScript: The Complete Guide to JavaScript Mastery Rating: 5 out of 5 stars5/5Instant SASS CSS How-to Rating: 5 out of 5 stars5/5Web Designer's Idea Book, Volume 4: Inspiration from the Best Web Design Trends, Themes and Styles Rating: 4 out of 5 stars4/5Responsive Web Design by Example : Beginner's Guide - Second Edition Rating: 0 out of 5 stars0 ratingsMastering Responsive Web Design with HTML5 and CSS3 Rating: 0 out of 5 stars0 ratingsMore Advanced CSS: Zombie in a Ballgown: Undead Institute Rating: 0 out of 5 stars0 ratingsExploring Web Components: Build Reusable UI Web Components with Standard Technologies (English Edition) Rating: 0 out of 5 stars0 ratingsResponsive Web Design With Html 5 & Css Rating: 0 out of 5 stars0 ratingsBootstrap 4 Site Blueprints Rating: 5 out of 5 stars5/5The Designer's Web Handbook: What You Need to Know to Create for the Web Rating: 0 out of 5 stars0 ratingsLearning jQuery 3 - Fifth Edition Rating: 0 out of 5 stars0 ratingsInstant HTML5 Responsive Table Design How-to Rating: 0 out of 5 stars0 ratingsMastering Bootstrap 4 Rating: 5 out of 5 stars5/5JavaScript for Modern Web Development: Building a Web Application Using HTML, CSS, and JavaScript Rating: 0 out of 5 stars0 ratingsWeb Developer's Reference Guide Rating: 0 out of 5 stars0 ratingsThe Strategic Web Designer: How to Confidently Navigate the Web Design Process Rating: 0 out of 5 stars0 ratingsExpress Guide: Learn Any Web Builder or Content Management System Rating: 0 out of 5 stars0 ratingsHTML & CSS Rating: 3 out of 5 stars3/5
Internet & Web For You
Coding For Dummies Rating: 5 out of 5 stars5/5How to Be Invisible: Protect Your Home, Your Children, Your Assets, and Your Life Rating: 4 out of 5 stars4/5Python: Learn Python in 24 Hours Rating: 4 out of 5 stars4/5The $1,000,000 Web Designer Guide: A Practical Guide for Wealth and Freedom as an Online Freelancer Rating: 4 out of 5 stars4/5Coding All-in-One For Dummies Rating: 4 out of 5 stars4/5JavaScript All-in-One For Dummies Rating: 5 out of 5 stars5/5The Digital Marketing Handbook: A Step-By-Step Guide to Creating Websites That Sell Rating: 5 out of 5 stars5/5Notion for Beginners: Notion for Work, Play, and Productivity Rating: 4 out of 5 stars4/5The Beginner's Affiliate Marketing Blueprint Rating: 4 out of 5 stars4/5SEO For Dummies Rating: 4 out of 5 stars4/548 Really Useful Web Sites Rating: 5 out of 5 stars5/5More Porn - Faster!: 50 Tips & Tools for Faster and More Efficient Porn Browsing Rating: 3 out of 5 stars3/5The Gothic Novel Collection Rating: 5 out of 5 stars5/5Web Design For Dummies Rating: 4 out of 5 stars4/52022 Adobe® Premiere Pro Guide For Filmmakers and YouTubers Rating: 5 out of 5 stars5/5Social Engineering: The Science of Human Hacking Rating: 3 out of 5 stars3/5No Place to Hide: Edward Snowden, the NSA, and the U.S. Surveillance State Rating: 4 out of 5 stars4/5Cybersecurity For Dummies Rating: 5 out of 5 stars5/5Introduction to Internet Scams and Fraud: Credit Card Theft, Work-At-Home Scams and Lottery Scams Rating: 4 out of 5 stars4/5Web Coding & Development All-in-One For Dummies Rating: 1 out of 5 stars1/5Ready, Set, Brand!: The Canva for Work Quickstart Guide Rating: 5 out of 5 stars5/5Kill All Normies: Online Culture Wars From 4Chan And Tumblr To Trump And The Alt-Right Rating: 3 out of 5 stars3/5Content Chemistry: The Illustrated Handbook for Content Marketing Rating: 5 out of 5 stars5/5Everybody Lies: Big Data, New Data, and What the Internet Can Tell Us About Who We Really Are Rating: 4 out of 5 stars4/5Tor and the Dark Art of Anonymity Rating: 5 out of 5 stars5/5Ultimate Guide for Being Anonymous: Hacking the Planet, #4 Rating: 5 out of 5 stars5/5Beginner's Guide To Starting An Etsy Print-On-Demand Shop Rating: 0 out of 5 stars0 ratings
Reviews for CSS Master
0 ratings0 reviews
Book preview
CSS Master - Tiffany B Brown
Chapter 1: Selectors
Understanding selectors is key to writing maintainable, scalable CSS. Selectors are the mechanism by which CSS rules are matched to elements. There are various ways to do this, and you’re probably familiar with most of them. Element type, class name, ID, and attribute selectors are all well supported and widely used.
In this chapter, we’ll firstly review the types of selectors. Then we’ll look at the current browser landscape for CSS selectors, with a focus on newer selectors defined by the Selectors Level 3 and Selectors Level 4 specifications.
This chapter stops short of being a comprehensive look at all selectors, as that could take up a whole book in itself. Instead, we’ll focus on selectors with good browser support that are likely to be useful in your current work. Some material may be old hat, but it’s included for context.
Types of Selectors
Selectors can be grouped into four basic types: simple, compound, combinator, and complex.
Simple selectors are the oldest form of CSS selector, and may be the type used most often. Simple selectors specify a single condition for matching elements. The universal selector (*) is a simple selector. So are type (or element) selectors such as p and pseudo-element selectors such as ::first-letter. Attribute selectors such as [hidden], class selectors such .message-error, and ID selectors such as #masthead also fall into this category.
Compound selectors, such as p:last-child or .message.error, are a sequence of simple selectors that reflect a set of simultaneous conditions to meet when applying rules to an element. In other words, .message.error will match
Combinator selectors express a relationship between elements. There are four:
the descendant combinator, as in article p
the child combinator (>), as in .sidebar > h2
the adjacent sibling combinator (+), as in ul + p
the general sibling combinator (~), as in p ~ figure
Rules are applied to the right-most element in a combinator selector when it fits the condition indicated by the combinator. We’ll discuss combinator selectors in detail later in the chapter.
Lastly, there are complex selectors. Complex selectors consist of one or more compound selectors separated by a combinator. The selector ul:not(.square) > a[rel=external] is an example of a complex selector.
Selectors can be grouped into what’s known as a selector list by separating them with a comma. Selector lists apply styles to elements that match any of the selectors in the list. For example, the rule article, div { padding: 20px; } adds 20 pixels of padding to both
Knowing what kind of selectors you’re working with will help you grasp one of the more confusing aspects of CSS: specificity. Keeping specificity low increases the reusability of your CSS rules. A selector such as #menu > .pop-open means that you can only use the .pop-open pattern when it’s a direct descendant of #menu, even if there are similar interactions elsewhere in your project.
We’ll return to specificity in Chapter 2, "CSS Architecture and Organization". For the rest of this chapter, however, we’ll discuss specific groups of selectors: combinators, attribute selectors, pseudo-elements, and pseudo-classes.
Combinators
As we saw above, a combinator is a character sequence that expresses a relationship between the selectors on either side of it. Using a combinator creates a complex selector. Using complex selectors can, in some cases, be the most concise way to define styles.
In the previous section, we listed the four combinators: descendant (via whitespace), child (>), adjacent sibling (+), and general sibling (~).
Let’s illustrate each of these combinators. We’ll use them to add styles to the HTML form shown below.
The HTML form that we’ll style using combinatorsThe form pictured above was created using the following chunk of HTML:
Buy Tickets to the Web Developer Gala
Tickets are $10 each. Dinner packages are an extra $5. All fields are required.
help>Limit 8
number value=1
name=quantity
id=quantity
step=1
min=1
max=8
>
help>Serves 2
number value=1
name=quantity
id=quantity
step=1
min=1
max=8
>
help>No spaces or dashes, please.
text id=ccn
name=ccn
placeholder=372000000000008
maxlength=16
size=16
>
help>Two-digit month>MM/Four-digit Year>YYYY
text id=expiration
name=expiration
placeholder=01/2018
maxlength=7
size=7
>
text id=name
name=name
placeholder=ex: John Q. Public
size=40
>
text id=name
name=name
placeholder=ex: 12345 Main Street, Apt 23
size=40
>
text id=city
name=city
placeholder=ex: Anytown
>
text id=state
name=state
placeholder=CA
maxlength=2
pattern=[A-W]{2}
size=2
>
text id=zip
name=zip
placeholder=12345
maxlength=5
pattern=0-9{5}
size=5
>
The Descendant Combinator
You’re probably quite familiar with the descendant combinator. It’s been around since the early days of CSS (though it lacked a proper name until CSS2.1). It’s widely used and widely supported.
The descendant combinator is simply a whitespace character. It separates the parent selector from its descendant, following the pattern A B, where B is an element contained by A. Let’s add some CSS to our markup from above and see how this works:
form h1 {
color: hsl(231, 48%, 48%);
}
We’ve just changed the color of our form title, the result of which can be seen below.
The effect of a descendant combinatorLet’s add some more CSS, this time to increase the size of our pricing message (Tickets are $10 each
). We’ll also make it hot pink:
form p {
font-size: 36px;
color: #c2185b;
}
There’s a problem with this selector, however, as you can see in the image below. Our selector is too broad.
Oops! Our selector is too broadWe’ve actually increased the size of the text in all of our form’s paragraphs, which isn’t what we want. How can we fix this? Let’s try the child combinator.
The Child Combinator
In contrast to the descendant combinator, the child combinator (>) selects only the immediate children of an element. It follows the pattern A > B, matching any element B where A is the immediate ancestor.
If elements were people, to use an analogy, the child combinator would match the child of the mother element. But the descendant combinator would also match her grandchildren, and great-grandchildren. Let’s modify our previous selector to use the child combinator:
form > p {
font-size: 36px;
}
Now only the direct children of form are affected, as shown in the image below.
The effect of the child combinatorThe Adjacent Sibling Combinator
With the adjacent sibling combinator (+), we can select elements that follow each other and have the same parent. It uses the pattern A + B. Styles are applied to B elements that are immediately preceded by A elements.
Let’s go back to our example. Notice that, in the Billing Address section, our labels and inputs sit next to each other. That means we can use the adjacent sibling combinator to make them sit on separate lines:
label + input {
display: block;
clear: both;
}
You can see the results in the image below.
Adjacent combinator to the rescueYou can see in the image above that some of our labels remain on the same line as their input fields. In those instances, there’s a element between the
Let’s look at another example that combines the universal selector (*) with a type selector:
* + fieldset {
margin: 5em 0;
}
This example adds a 5em margin to the top and bottom of every
Using the adjacent sibling combinator to adjust the bottom margin for our fieldset elementsSince we’re using the universal selector, there’s no need to worry about whether the previous element is another
More Uses of the Adjacent Sibling Selector
Heydon Pickering explores more clever uses of the adjacent sibling selector in his article "Axiomatic CSS and Lobotomized Owls".
The General Sibling Combinator
With the general sibling combinator (~) we can select elements that share the same parent without considering whether they’re adjacent. Given the pattern A ~ B, this selector matches all B elements that are preceded by an A element.
Let’s look at the Number of Tickets field again. Its markup looks like this:
help>Limit 8
number value=1
name=quantity
id=quantity
step=1
min=1
max=8
>
Our element follows the
label ~ input {
display: block;
}
Now all of our elements sit on a separate line from their
The ~ combinator targets sibling elements, regardless of whether they’re adjacentBecause the general sibling combinator matches any subsequent sibling, you’ll want to use it judiciously. Consider the markup and CSS below:
en-US>
utf-8>
h1 ~ p {
background: yellow
}
h2 + p {
outline: 5px dotted #009;
}
In This Essay, I Will
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce odio leo, sollicitudin vel mattis eget.…
Nulla sit amet neque eleifend diam aliquam rhoncus. Donec id congue est. Aliquam sagittis euismod tristique.…
Show how the general sibling combinator works
Proin condimentum elit sapien, ut tempor nisl porta quis. …
Here we’ve used the general sibling combinator with an
element. As a result,
every paragraph element that follows anelement has a yellow background. This includes the paragraph that follows the
heading, as shown below.
Remember, the general sibling combinator matches every element B that follows A, regardless of its position in the documentIf you have control over the document’s markup, I’d recommend using a class selector instead of the general sibling combinator. The general sibling combinator makes it too easy to accidentally style more elements than you intended to.
Attribute Selectors
Introduced with the CSS Level 2 Specification, attribute selectors make it possible to style elements based on the presence of an attribute, such as [controls] for a media player, or [disabled] for a form field.
You can also use attribute selectors to match elements based on the presence of an attribute and its value. For example, to style submit buttons, you might use the following CSS:
[type=submit] {
background: seagreen;
border: 0;
border-radius: 1000px;
color: #fff;
font-size: 18pt;
padding: 10px 20px;
}
There are also several attribute selectors for partially matching attribute values, as well as substrings. Being able to target partially matching attribute values is one of my favorite features of CSS selectors. When used thoughtfully, they can reduce the number of rules and declarations you need to write. We’ll look at them shortly. Most of the attribute selectors we’ll cover are old hat. I’ve included them, however, for context and completeness.
A Note About Quotes
Quoting the values of attribute selectors is optional in most cases. Both [type=checkbox] and [type=checkbox
] are valid and well-supported syntaxes for attribute selectors. Use quotes when the attribute’s value contains spaces or punctuation characters, such as [class=piechart animated
], [data-action=modal:close
] or [id='section-2.2'].
Matching Space-separated Attribute Values
Although we can select elements based on an attribute value, as discussed above, a selector such as [rel=external] won’t match / rel=external citation
>, because the rel value isn’t exactly external. Instead, we need to use a selector that can accommodate space-separated values, which takes the form of [att~=val].
The space-separated attribute value selector matches elements with the attribute (att) and a list of values, one of which is val. This can be any attribute that accepts space-separated values, including class or data-*.
Space-separated lists of attributes are admittedly uncommon. They’re sometimes used with the rel attribute and microformats to describe relationships between people and documents. As an example, we might mark up external links like so:
http://bob.example.com/ rel=external friend
>Bob
http://maria.example.com/ rel=external acquaintance
>María
http://ifeoma.example.com/ rel=external colleague
>Ifeoma
We can then use this presence-based attribute selector to match links that contain friend as one of its attribute values:
[rel~=friend] {
font-size: 2em;
background: #eee;
padding: 4px;
text-decoration: none;
border-bottom: 3px solid #ccc;
}
[rel~=friend]:link, [rel~=friend]:visited {
color: #34444C;
}
[rel~=friend]:hover{
background: #ffeb3b;
border-color: #ffc107;
}
The result of this is shown in the image below.
A link to Bob’s website styled using an attribute selectorMatching Hyphenated Attribute Values
One of the more interesting tasks we can do with attribute selectors is to use [attr|=val] to match the first part of an attribute value before the first hyphen. For example, [lang|=en] would match an element like
en-US>.
The main purpose of this selector is for working with languages and language codes, such as en-US and es-MX.
Let’s say we have some markup like this:
fr-FR>Tout le monde
All the world
, or Everyone
We can italicize our French text and add language-appropriate angle quotes (« and ») to either side of it:
[lang|=fr
] {
font-style: italic;
}
[lang|=fr
] q:before{
content: '\00AB'; /* Left angle quote */
}
[lang|=fr
] q:after{
content: '\00BB'; /* Right angle quote */
}
What’s cool about this selector is that it works even if there’s no hyphen. So the styles above would also apply to
fr>. And we can further limit the scope of these selectors by adding an element selector, such as p[lang|=fr
].
This selector isn’t limited to language codes. We can use it with any hyphenated attribute value. Consider the following markup:
U.S. Meets Climate Goals 5 Years Early
Lorem ipsum dolor sit amet, consectetur adipisicing ....
Prince-Bythewood, Duvernay Among Nominees At Oscars
Lorem ipsum dolor sit amet, consectetur adipisicing ....
New York Knicks win NBA title
Lorem ipsum dolor sit amet, consectetur adipisicing ....
GrubDash to Hire 3,000 Drivers, Offer Benefits
Lorem ipsum dolor sit amet, consectetur adipisicing ....
These are all article promos or teasers. They share some of the same visual characteristics and behavior, along with classes prefixed with promo. Here, too, we can use the hyphenated attribute selector to match these class names:
[class|=promo
] {
border-top: 5px solid #4caf50;
color: #555;
line-height: 1.3;
padding-top: .5em;
}
[class|=promo
] h3 {
color: #000;
font-size: 1.2em;
margin:0;
}
[class|=promo
] p {
margin: 0 0 1em;
}
Follow this up with specific border colors for each section type, and you’ll achieve something along the lines of the layout pictured below.
Using hyphenated attributes to style elementsWe can also use this selector with ID names. For example, [id|=global] would match #global-footer, #global-menu, and so on.
Matching Attribute Values by Substring
We can also select elements when the attribute values match a particular substring using [att^=val], [att$=val] and [att*=val].
The ^= selector matches a substring at the beginning of an attribute value. For example, think about links using tel: (non-standard) or mailto:. Since they behave differently from other hyperlinks, it makes sense to style them differently just as a hint to the user. Take a Call this business
link:
tel:+14045555555>Call this business
We can select this and other tel: links by using [href^=tel:
]. Let’s add some declarations:
[href^=tel:
] {
background: #2196f3 url(../../Images/phone-icon.svg) 10px center / 20px auto no-repeat;
border-radius: 100px;
padding: .5em 1em .5em 2em;
}
You can see the result in the image below.
Our new “Call this business” buttonThe $= selector matches a substring at the end of an attribute value. If, for example, we wanted to give a special color to PDF file links, we could use a[href$=.pdf
]:
a[href$=.pdf
] {
color: #e91e63;
}
This selector would also be handy for matching elements whose attribute values end with the same suffix. For example, you could match both
The *= selector matches a substring in any position within the attribute value. Using the selector [class*=sidebar], we could select an element with a class of sports-sidebar-a, along with elements with the classes sports-sidebar and arts-sidebar.
Matching Attribute Values by Case
CSS is, for the most part, a case-insensitive language. Both color: tomato and COLOR: TOMATO do the same thing. Both p {…} and P {…} will style paragraphs in HTML, whether the HTML uses
or
. The same applies with attribute names, where [href] and [HREF] will both match href=…
and HREF=…
.
However, the same doesn’t apply to attribute values. Letter case matters with these. In the following markup, the ID attribute for our
The identifier for this tag mixes uppercase and lowercase letters.
To style the
But there is an alternative. We could instead use case-insensitive attribute matching. It’s a feature defined by the Selectors Level 4 specification.
Case-insensitive attribute matching uses the i flag to indicate that these styles should be applied to any case combination:
[id=mixedcaseidexample i] {
color: blue;
}
Now our selector will match the ID attribute whether its value is mixedcaseidexample, MixedCaseIDExample, or mIxEdCaSeIdExAmPlE.
In some cases, you may want to enforce case-sensitive value matching. To enforce case-sensitive matching, use the s flag:
[id=mixedcaseidexample
s] {
color: orange;
}
The s flag matches #mixedcaseidexample, but not #MixedCaseIDExample or #mIxEdCaSeIdExAmPlE.
Pseudo-classes and Pseudo-elements
Most of the new selectors added in CSS3 and CSS4 are not attribute selectors at all. They’re pseudo-classes and pseudo-elements.
Though you’ve probably used pseudo-classes and pseudo-elements in your CSS, you may not have thought about what they are or how they differ from each other.
Pseudo-classes let us style objects based on information—such as their state—that’s distinct from the document tree, or that can’t be expressed using simple selectors. For example, an element can only have a hover or focus state once the user interacts with it. With the :hover and :focus pseudo-classes, we can define styles for those states. Otherwise, we’d have to rely on scripting to add and remove class names.
Pseudo-elements, on the other hand, let us style elements that aren’t directly present in the document tree. HTML doesn’t define a firstletter element, so we need another way to select it. The ::first-letter pseudo-element gives us that capability.
Beware of Universal Selection
Using pseudo-classes and pseudo-elements without a simple selector is the equivalent of using them with the universal selector. For a selector such as :not([type=radio]), every element that lacks a type attribute and value of radio will match—including and . To prevent this, use :not() as part of a compound selector, such as with a class name or element, as in p:not(.error).
In the same way, using class names, IDs and attribute selectors on their own applies them universally. For example, .warning and [type=radio] are the same as *.warning and *[type=radio].
Pseudo-elements
The CSS Pseudo-elements Module Level 4 specification clarifies behavior for existing pseudo-elements and defines several new ones. We’ll focus on the ones that currently have browser support:
::after inserts additional generated content after the content of an element
::before inserts additional generated content before the content of an element
::first–letter selects the first letter of an element
::first–line selects the first line of an element
::marker styles bullets and numbers for list items and the
::placeholder styles placeholder text for form controls using the placeholder attribute
::selection styles text selected by the cursor
Of these, ::first–letter, ::first–line, ::selection, ::marker and ::placeholder affect content that’s part of the document source. The ::before and ::after pseudo-elements, on the other hand, inject content into a document. Let’s look at each of these pseudo-elements more closely.
::before and ::after
Most pseudo-elements allow us to select content that’s already part of the document source—that is, the HTML you authored—but that’s not specified by the language. But ::before and ::after work differently. These pseudo-elements add generated content to the document tree. This content doesn’t exist in the HTML source, but it’s available visually.
Why would you want to use generated content? You might, for example, want to indicate which form fields are required by adding content after their label:
/* Apply to the label element associated with a required field */
.required::after {
content: ' (Required) ';
color: #c00;
font-size: .8em;
}
Required form fields use the required HTML property. Since that information is already available to the DOM, using ::before or ::after to add helper text is supplemental. It isn’t critical content, so it’s okay that it’s not part of the document source.
Generated Content and Accessibility
Some screen reader and browser combinations recognize and read generated content, but most don’t. You can’t be sure that content generated using ::before or ::after will be available to assistive technology users. You can read more about this in Leonie Watson’s piece "Accessibility support for CSS generated content".
Another use case for ::before or ::after is adding a prefix or suffix to content. For example, the form mentioned above might include helper text, as shown here:
password id=password
name=password
>
password id=password2
name=password2
>
helptext>Longer passwords are stronger.
Let’s enclose our helper text in red parentheses using ::before and ::after:
.helptext::before,
.helptext::after {
color: hsl(340, 82%, 52%);
}
.helptext::before {
content: '( ';
}
.helptext::after {
content: ')';
}
The result is shown below.
Using ::before and ::after to add supplemental contentBoth ::before and ::after behave similarly to other descendant elements. They inherit the inheritable properties of their parent, and are contained within it. They also interact with other element boxes as though they were true elements.
One Pseudo-element per Selector
Currently, only one pseudo-element is allowed per selector. A selector such as p::first-line::before is invalid and unsupported.
This means that we can use ::before and ::after with CSS Grid and Flexbox. One use case is decorated headings, such as the one shown below.
Using Grid layout with ::before and ::after to create decorated headingsThe CSS required to create this heading is as follows:
h1 {
display: grid;
grid-template-columns: 1fr auto 1fr;
gap: 3rem;
}
h1::before,
h1::after {
content: '\00a0';
background: url('decoration.svg') repeat-x center / 50% auto;
}
You can read more about CSS Grid and Flexbox layout in Chapter 5, "Layouts".
Creating Typographic Effects with ::first-letter
While the ::before and ::after pseudo-elements inject content, ::first-letter works with content that exists as part of the document source. With ::first-letter, we can create initial letter effects, such as drop caps, as you might see in a magazine or book layout.
Initial and Drop Caps
An initial capital is an uppercase letter at the start of a block of text that’s set in a larger font size than the rest of the body copy. A drop capital (or drop cap) is similar to an initial capital, but is inset into the first paragraph by at least two lines.
This CSS snippet adds an initial capital letter to every
element in our document:
p::first-letter {
font-family: serif;
font-weight: bold;
font-size: 3em;
font-style: italic;
color: #3f51b5;
}
The result is shown below.
Creating initial caps with the ::first-letter pseudo-elementAs you may have noticed from the image above, ::first–letter will affect the line-height of the first line if you’ve set a unitless line-height for the element. In this case, each
element inherits a line-height value of 1.5 from the element. There are three ways to mitigate this:
Decrease the value of line-height for the ::first–letter pseudo-element. A value of .5 seems to work well most of the time, depending on the font.
Set a line-height with units on the ::first–letter pseudo-element.
Set a line-height with units on either the or the ::first–letter parent.
The first option preserves the vertical rhythm that comes with using a unitless line-height. The second option limits the side effects of using a fixed