On page 397 of the class text, is the topic of Containing Floats. This short lesson goes over the examples given in the class text. There are three sections here. The first two are examples, and the third section corrects an error in the class text.
Sometimes an image that has been floated doesn't appear to fit inside the element it is contained in. An example is the following:
<style>
#container {
background-color: #f2f5d5;
border: 2px dashed green;
padding: 1em;
}
img {
float: left;
width: 160px;
padding: 2%;
}
</style>
<body>
<div id="container">
<img src="ice cream.jpg" width="160" height="160">
<h3>Sundae Buffet</h3>
<p>Topping List</p>
</div>
</body>
Here, the image ice cream.jpg is contained in the <div> element container along with the text "Sundae Buffet" and "Topping List".
In the <style> section, there is an id selector named container.
It has the properties of a background color of #f2f5d5, a green dashed border 2px wide, and there is 1em of padding around the content.
The id selector is used in the <div> element.
In the style section the img selector is used to float the image to the left, it gives it a width of 160px, and allows 2% padding around it.
When you open this in your browser, it will look like this:
The height of the <div> container is determined by the number of lines of text inside it. Because there are only two lines of text, the <div> container is sized to fit around that text.
The image, ice cream.jpg, is being floated, so it doesn't take up space in the <div> container. A floated image is outside the normal flow of the website.
Because the <div> element only has the two lines of text, it is not high enough for the ice cream.jpg image to appear to fit inside it. And so the floated image is hanging out the bottom of the <div> element, which doesn't look good.
To fix this, the <div> element can be floated as well. Both the <div> and the image can be floated to the left by including the float: left; declaration and the width: 100%; declaration , in the id selector named "container", as shown here:
<style>
#container {
float: left;
width: 100%;
background-color: #f2f5d5;
border: 2px dashed green;
padding: 1em;
}
img {
float: left;
width: 160px;
padding: 2%;
}
</style>
<body>
<div id="container">
<img src="ice cream.jpg" width="160" height="160">
<h3>Sundae Buffet</h3>
<p>Topping List</p>
</div>
</body>
When you open this in your browser, it will look like this:
On page 397 of the class text, is another example of Containing Floats, this time using text instead of an image. The following example has two paragraphs of text, which are being floated to the left inside the <div> element container.
The following markup produces the result shown at the bottom of Illustration 15-10 on page 387.
<style>
#container {
background-color: #f2f5d5;
border: 2px dashed green;
padding: 1em;
}
p {
float: left;
width: 44%;
padding: 2%;
}
</style>
<body>
<div id="container">
<p>If you float all the elements in a container element, there
will be no elements remaining in the flow to hold the
containing element open. This phenomenon is illustrated
in FIGURE 15-10. The #container div contains two paragraphs.
The view of the normal flow (top) shows that the
#container has a background color and border that wraps
around the content.</p>
<p>However, when both paragraphs (that is, all of the content
within the div) are floated, as shown in the figure on the
bottom), the element box for the #container closes up to
a height of zero, leaving the floats hanging down below
(you can still see the empty border at the top). There’s no
content left in the normal flow to give the containing div
height. This clearly is not the effect we are after.</p>
</div>
</body>
In the style section, the p selector is used to float the text to the left, with a width of 44%, and with 2% padding around it.
When you open this in your browser, it will look like this:
The entire contents within the <div> element are the two paragraphs of text (which I copied from page 397 of the class text). But since the text is being floated, that takes it out of the normal flow of the website, therefore it doesn't get contained within the <div>.
And so the <div> only has the background color, dashed green border, and 2em of padding around nothing. And the floated text, which is outside the normal flow of the website, ends up below it.
To fix this, the <div> element which contains the text, can also be floated as well, as Example 1 above showed.
So now both the <div> and the text are being floated to the left by including the float: left; declaration and the width: 100%; declaration , in the id selector named "container", as shown here:
<style>
#container {
float: left;
width: 100%;
background-color: #f2f5d5;
border: 2px dashed green;
padding: 1em;
}
p {
float: left;
width: 44%;
padding: 2%;
}
</style>
<body>
<div id="container">
<p>If you float all the elements in a container element, there
will be no elements remaining in the flow to hold the
containing element open. This phenomenon is illustrated
in FIGURE 15-10. The #container div contains two paragraphs.
The view of the normal flow (top) shows that the
#container has a background color and border that wraps
around the content.</p>
<p>However, when both paragraphs (that is, all of the content
within the div) are floated, as shown in the figure on the
bottom), the element box for the #container closes up to
a height of zero, leaving the floats hanging down below
(you can still see the empty border at the top). There’s no
content left in the normal flow to give the containing div
height. This clearly is not the effect we are after.</p>
</div>
</body>
When you open this in your browser, it will look like this:
Pseudo-class verses pseudo-element
Now here is the confusing part. On page 398, the author uses something we briefly studied back in Chapter 13, a pseudo-element. Pseudo-elements are different from the pseudo-classes we also learned about earlier.
The pseudo-classes we learned about were the special selectors that specify a particular style for links that have not yet been selected, for links that have been visited, for links that are being clicked, for links the mouse is hovering over, and so on.
A pseudo-element is used to style specified parts of an element. For example, it can be used to style the first letter, or line, of an element, or insert content before, or after, the content of an element. You can find out more about pseudo-elements at the w3schools.com website here:
https://www.w3schools.com/css/css_pseudo_elements.asp
The basic syntax of a pseudo-element is:
selector::pseudo-element {
property: value;
}
Notice the two colons that are used in pseudo-elements. This contrasts with the single colon that is used with pseudo-classes:
selector:pseudo-class {
property: value;
}
You can review more about pseudo-classes on the w3schools.com website here:
https://www.w3schools.com/css/css_pseudo_classes.asp
The class text on page 398 incorrectly uses the "clearfix" technique with the :after pseudo-element, as shown here:
<style>
#container:after {
content: " ";
display: block;
clear: both;
background-color: #f2f5d5;
border: 2px dashed green;
padding: 1em;
}
p {
float: left;
width: 44%;
padding: 2%;
}
</style>
<body>
<div id="container">
<p>If you float all the elements in a container element, there
will be no elements remaining in the flow to hold the
containing element open. This phenomenon is illustrated
in FIGURE 15-10. The #container div contains two paragraphs.
The view of the normal flow (top) shows that the
#container has a background color and border that wraps
around the content.</p>
<p>However, when both paragraphs (that is, all of the content
within the div) are floated, as shown in the figure on the
bottom), the element box for the #container closes up to
a height of zero, leaving the floats hanging down below
(you can still see the empty border at the top). There’s no
content left in the normal flow to give the containing div
height. This clearly is not the effect we are after.</p>
</div>
</body>
There are two major problems with the the above markup, as taken from the class text on page 398.
Problem #1
First, between the selector (#container)and the pseudo-element (after) are supposed to be 2 colons. In the class text, only one is used:
#container:after {
content: " ";
display: block;
clear: both;
background-color: #f2f5d5; /*light green*/
border: 2px dashed green;
padding: 1em;
}
Problem #2
The second problem is that the mark up on page 398, as show below, simply doesn't work, even if you use two colons between the selector and the pseudo-element .
#container::after {
content: " ";
display: block;
clear: both;
background-color: #f2f5d5; /*light green*/
border: 2px dashed green;
padding: 1em;
}
When you open this in your browser, it will look like this:
That's not what we want.
So I looked into this problem at w3schools here:
https://www.w3schools.com/howto/howto_css_clearfix.asp
and here:
https://www.w3schools.com/css/css_float_clear.asp
w3schools has two solutions that can fix this.
Solution #1
Their first solution that w3schools.com recommends, is to entirely remove this markup,
#container:after {
content: " ";
display: block;
clear: both;
and replace it with the overflow: auto; declaration.
When applied to this example, it is the following:
<style>
#container {
overflow: auto;
background-color: #f2f5d5;
border: 2px dashed green;
padding: 1em;
}
p {
float: left;
width: 44%;
padding: 2%;
}
</style>
<body>
<div id="container">
<p>If you float all the elements in a container element, there
will be no elements remaining in the flow to hold the
containing element open. This phenomenon is illustrated
in FIGURE 15-10. The #container div contains two paragraphs.
The view of the normal flow (top) shows that the
#container has a background color and border that wraps
around the content.</p>
<p>However, when both paragraphs (that is, all of the content
within the div) are floated, as shown in the figure on the
bottom), the element box for the #container closes up to
a height of zero, leaving the floats hanging down below
(you can still see the empty border at the top). There’s no
content left in the normal flow to give the containing div
height. This clearly is not the effect we are after.</p>
</div>
</body>
The only declaration (i.e. property and value) that is needed is overflow: auto;.
When you open this in your browser, the two paragraphs of text are inside the container like this:
The w3schools example of using the overflow: auto; declaration is here for you to experiment with:
https://www.w3schools.com/css/tryit.asp?filename=trycss_layout_clearfix
Solution #2
The second solution requires two changes to the markup.
First, is to separate out the <div> declarations for background-color (background-color: #f2f5d5;), border (border: 2px dashed green;), and padding properties (padding: 1em;) from the container id. This was not needed for Solution #1 above.
Second, on the w3schools website here,
https://www.w3schools.com/howto/howto_css_clearfix.asp
they note that the overflow:auto; "clearfix" method works well as long as you are able to keep control of your margins and padding (else you might see scrollbars). w3schools.com says that a new, modern "clearfix" hack however, is safer to use, and the following generic code is used for most webpages:
.clearfix::after {
content: "";
clear: both;
display: table;
}
This is illustrated in the w3schools example here:
https://www.w3schools.com/css/tryit.asp?filename=trycss_layout_clearfix2
The w3schools example is as follows:
<html>
<head>
<style>
div {
border: 3px solid #4CAF50;
padding: 5px;
}
.img1 {
float: right;
}
.clearfix::after {
content: "";
clear: both;
display: table;
}
.img2 {
float: right;
}
</style>
</head>
<body>
<p>In this example, the image is taller than the element containing it, and it is floated, so it overflows outside of its container:</p>
<div>
<h2>Without Clearfix</h2>
<img class="img1" src="pineapple.jpg" alt="Pineapple" width="170" height="170">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus imperdiet, nulla et dictum interdum...
</div>
<p style="clear:right">Add the clearfix hack to the containing element, to fix this problem:</p>
<div class="clearfix">
<h2>With Clearfix</h2>
<img class="img2" src="pineapple.jpg" alt="Pineapple" width="170" height="170">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus imperdiet, nulla et dictum interdum...
</div>
</body>
</html>
The div selector, with its two declarations, is all by itself in the style section:
div {
border: 3px solid #4CAF50;
padding: 5px;
}
And the "clearfix" solution is below it:
.clearfix::after {
content: "";
clear: both;
display: table;
}
There are three things to notice here about the "clearfix" solution.
First, you don't need to use the class name, or id name, of "clearfix". Using the word "container", or any other word, is just as valid.
Second, the w3schools.com example uses the display: table; declaration whereas in the class text it is display: block;. Either works the same.
Third, since after is a pseudo-element, two colons are needed between the id (#container) and after.
To fix the example from page 398 in the class text, the div selector is therefore used along with the new "clearfix" method. The corrected solution is therefore:
<style>
#container::after {
content: "";
clear: both;
display: block;
}
div {
background-color: #f2f5d5;
border: 2px dashed green;
padding: 1em;
}
p {
float: left;
width: 44%;
padding: 2%;
}
</style>
<body>
<div id="container">
<p>If you float all the elements in a container element, there
will be no elements remaining in the flow to hold the
containing element open. This phenomenon is illustrated
in FIGURE 15-10. The #container div contains two paragraphs.
The view of the normal flow (top) shows that the
#container has a background color and border that wraps
around the content.</p>
<p>However, when both paragraphs (that is, all of the content
within the div) are floated, as shown in the figure on the
bottom), the element box for the #container closes up to
a height of zero, leaving the floats hanging down below
(you can still see the empty border at the top). There’s no
content left in the normal flow to give the containing div
height. This clearly is not the effect we are after.</p>
</div>
</body>
When you open this in your browser, it will look like this: