Stephanie Eckles
Posted on March 13, 2020
In this post, we will learn about CSS properties and layout patterns useful for styling content such as for a blog, including
- how to center website content
- about special selectors
- how margin collapsing works
- how to use Inspector to help create definitions for complex properties like
linear-gradient
- how to make a circular image with one line of CSS
This is the thirteenth post and video in a series on learning web development. Learn more about the series and see the post schedule >
You may want to refer back to the first lesson that created our initial blog HTML, episode 5:
You may watch the following video or follow along with the expanded transcript that follows.
To begin this lesson, open the starter project you began in episode 1, or review the source files from episode 12.
To begin this lesson, open our project in VSCode.
In the Terminal, type the start command npm run start
to run the project.
Open blog-layout.html
in VSCode, and organize your screen to be split with the browser. Then update the browser url to include /blog-layout.html
.
Now, this page may seem a little shocking at this point since it is inheriting all of our styles due to linking to our single style.css
file. We're no longer benefitting from that, so let's first create a new CSS file called blog-layout.css
.
Then in our HTML file, update the stylesheet link
in the <head>
from style.css
to blog-layout.css
and save. Now we're back to default browser styles.
<link rel="stylesheet" href="blog-layout.css" />
We'll first create a rule for body
:
body {
font-family: sans-serif;
color: #222;
}
I chose the color
value of #222
because an off-black is recommended as a little easier on the eyes when reading long-form content like a blog post.
Next, let's adjust our typographic scale, which means the size assigned to each typography element.
Before that, let's temporarily comment out the image so we can focus on the type.
<!-- <img src="http://placecorgi.com/200x150" alt="Good corgi doggo" align="left"> -->
For the type, we'll do something similar to what we defined originally in style.css
, including a rule to reset the margins. But we'll reduce our rules to cover h1-h3 for this demo.
h1, h2, h3 {
margin: 0 0 0.35em;
}
h1 {
font-size: 40px;
}
h2 {
font-size: 28px;
}
h3 {
font-size: 20px;
}
Looking at our page, it feels like the spacing is a little off around the paragraphs. Let's try adding a margin
definition for p
:
p {
margin: 0 0 1.15em;
}
That feels a little better, but let's duplicate each paragraph, and then remove some words out of each paragraph to mimic real text a bit more. Then save and let's review.
It looks nice between paragraphs, but it would be nice to use a bit more space to emphasize the sections created by use of the h2
. For this, we could use a class, but that would require remembering to use the class each time we added an h2
.
Instead, we can use the adjacent sibling selector which is +
to select h2
that follow p
and create the following rule:
p + h2 {
margin-top: 1.5em;
}
Save, then with Inspector we can see that there is only margin-top
on the second h2
because it is the only one following a p
.
Inspector also helps us see a few other interesting things about how the margin-top
was applied. First, since we used the relative em
unit, the space is equal to 1.5 * 28px, since the font-size
of the h2
is set to 28px
which on the Computed tab we can see becomes 42px
.
But wait - isn't there a margin-bottom
on every p
? If we inspect the paragraph prior to the h2
we see there is a computed margin-bottom
of 18.4px
and then if we hover the h2
we see it's margin-top
extends to the bottom of the paragraph, not to the bottom of the paragraph's margin.
This is due to a particular behavior of margins which is called "collapsing". Competing margins collapse into each other with the smaller margin being collapsed into the larger margin.
The takeaway here is that if you have set equal margins on two bordering elements, like 16px
, the space will not be double the value at 32px
, but rather collapse to be 16px
total.
You can refresh the page to clear the element.style
.
With our window half-width, we're missing the whole picture we have with our layout, so let's extend both VSCode and the browser back to full-width and then move beyond typography.
Open blog-layout.html
in VSCode, and let's review our structure. Our primary containing elements are header
, main
, and footer
. Let's go ahead and remove the <hr>
we added in the HTML lesson since we'll replace it with CSS.
With the browser window full-width, it's clear that our layout is aligned to the screen left, which make sense as all the containing elements are block elements and we learned previously that that's their default behavior. But you have likely noticed from viewing other websites that there is generally:
- A max-width set for the main content area; and
- The main content area is centered in the browser window
Switch back to our CSS file, and let's add a new rule:
header, main, footer {
max-width: 800px;
margin-left: auto;
margin-right: auto;
}
Save, and you'll see our content now appears more centered.
If we Inspect, you can see that's the result of adding the auto
margins. The auto
keyword is unique to margin
and tells the browser to compute the value of extra space. We've used it on both sides, so it's effectively pushed our containers to the center.
Using Inspector, you can toggle off the margin-right
definition and then see how the remaining margin-left: auto
rule has caused the containers to slide all the way to the right side.
However, if we test toggling off the max-width
rule, there is no extra space left around each element which eliminates the centering behavior.
This is looking good, but we want our header to stand out more, so let's add a rule:
header {
background-color: rebeccapurple;
color: #fff;
padding: 24px;
}
Save, and you may agree that's not quite the effect we were going for. It would be nice if the background-color
stretched across the window. But we placed our max-width
rule on the header directly, so it's limiting the width of the background as well.
It's time to introduce a utility class to handle the width and centering, so let's change that rule to use the selector for a class: .container
and save.
/* header, main, footer { */
.container {
max-width: 800px;
margin-left: auto;
margin-right: auto;
padding: 24px;
}
Let's also move the padding rule from header
into the .container
class. Unlike margin
, padding does not collapse since it's inside the element it's defined on. This will help create visual space between our elements.
Then in our HTML, we'll make 3 adjustments. First, wrap the content of header
and footer
with a div
and include the container
class.
<!-- inside `header` and `footer` -->
<div class="container">
<!-- content -->
</div>
Inside main
we already have the child element of article
so we can add the container class to that, then save and review.
<main>
<article class="container">
That's more like it!
But there's still a bit of leftover space. Using Inspector to explore, we find that margin
on body
is the culprit, so on the body
rule let's add the definition margin: 0
and save.
Now let's add a new rule to the footer
:
footer {
border-top: 2px solid rebeccapurple;
}
Save - and hold on, that did more than we wanted it to!
There's now also a border within our blockquote
which also contains a footer
element.
We could create a utility class to apply a border, but for purposes of this lesson, let's use the child combinator selector which is the >
and means to select only elements that are a direct child of the qualifying selector. We'll modify our selector to body > footer
and save. Now the footer that is nested within blockquote
is unaffected by this rule.
Speaking of our blockquote
, let's give him some styling love, too.
It can be helpful to use the element.style
section to try out new styles before you commit to them in your stylesheet, and also to take advantage of the helpers provided by the browser, so let's select the blockquote
and try it.
Add background
and then if we begin to type linear-gradient
the browser not only autocompletes but provides a default value. For things like gradients, developing in the browser is extra useful because the syntax is tricker than your average definition.
Instead of the pure black the browser defaulted to, let's update to a softer value that's a tint of rebeccapurple
. To figure out that value, let's Inspect header
and open the color picker, and slide the picker icon at roughly a 45 degree angle toward the top left until it's on a really light purple. Click on the generated hex value and copy it. Don't worry about reverting the header
value since we're focusing on the blockquote
right now.
Return to the blockquote
and update the value of black
in the linear-gradient
to the value you copied. The value I selected is #eddbff
.
We can now copy the background definition, and move it to our stylesheet, where we'll add a few more properties to complete the rule:
blockquote {
background: linear-gradient(45deg, #eddbff, transparent);
color: rebeccapurple;
margin-left: 0;
margin-right: 0;
padding: 1em;
border-radius: 4px;
}
We're almost done, but we need to deal with our image, so let's uncomment that to add it back in. Let's also update the src
url to drop the x150
which was added in error in the HTML lesson.
The main issue here is the lack of space between the img
and the surrounding content. Now, we want a rule that won't affect every img
we may add to the site, just left-aligned images in our articles.
We also committed an error in our HTML lesson - which was done purely because we hadn't learned CSS yet! That error was using the align
attribute which is actually what is called "deprecated". Deprecation means it used to be a valid attribute but is no longer recommended and support for it could be dropped in future browser versions, so we shouldn't rely on it.
Instead let's create a utility class:
.img--align-left {
float: left; /* replaces the style previously inherited by the browser */
margin: 0 16px 16px 0;
}
Then on the img
HTML, remove the align
attribute and replace it with class="img--align-left"
.
<img src="http://placecorgi.com/200" alt="Good corgi doggo" class="img--align-left" />
Save, and it's looking better with the margin
added to give it some breathing room.
Let's add one more property for visual flair and use border-radius: 50%
and save. You can see that the image now appears as a circle! 50%
is a special value that can produce a circle, but only on square elements. If the element is not square, it will begin to have a more oval appearance.
Our use of the placecorgi service is returning a 200px
square image, which mimics an image that you may add into your blog from a CMS such as WordPress where you could also define precise dimensions, therefore ensuring a square base image. We'll explore a different method of ensuring visually consistent image sizes in our capstone project.
Finally, let's update our margin
to actually use a negative value instead of 0
for the margin-left
, so the definition becomes 0 16px 16px -20px
and save. This allows it to tuck into the space created by the padding
defined by .container
but not extend out beyond the boundary of the article
.
Here's the final result on CodePen:
Next up in Episode 14: Styling a Card Layout
Posted on March 13, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.