Previously, we worked with blocks separately. Now, let’s try working with the overall structure.

In general, any website consists of a set of rows and columns. We already know how to create rows, i.e. whatever div we insert, it occupies the entire row:

<div class="block"></div>

<style>
    .block {
        border: 1px solid black;
        height: 1rem; /* explicitly specified the height of the block in rem units, which is equal to the standard height of one row */
         margin-bottom: 0.5rem; /* bottom margin */
    }
</style>

and if I add three blocks, they will all occupy one line

<div class="block"></div>
<div class="block"></div>
<div class="block"></div>

And here the question arises: what if I want them to be displayed not line by line, but all together in one line?

To do this, we will use the capabilities of a special set of styles called flex.

First, let’s wrap all three of our blocks in a single div and assign it the row class:

<div class="row">
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
</div>

Visually, nothing will change.

Now let’s write the styles for the row class.

<style>
    .block { /* ... */ }

    .row {
        display: flex;
    }
</style>

And immediately all our blocks will collapse into a row, and only the borders will remain visible

And now, most importantly, we will specify how much relative space our blocks should occupy in the row. To do this, we use the flex-grow property. Let’s add it to the block class

<style>
    .block {
        border: 1px solid black;
        height: 1rem;
        margin-bottom: 0.5rem;
        flex-grow: 1; /* added */
    }

    .row {
        display: flex;
    }
</style>

And now all the blocks are stretched across the row, and since they all have the same flex-grow, each one takes up an equal share of 1:

I can make any block twice as large as the others. To do this, I will simply add a style to it and specify the value flex-grow: 2

<div class="row">
    <div class="block"></div>
    <div class="block" style="flex-grow: 2;"></div>
    <div class="block"></div>
</div>

Now the second block takes up two shares, and the rest take up one each.

However, all this starts to behave very interestingly when we don’t just have empty blocks, but also add some content to them.

Connecting a third-party library

To make it more fun, I will use icons along with the text.

There is a wonderful library of icons called fontawesome with a huge number of icons for every colour and taste.

To start using it in your file, you need to add a link to its styles. This is done slightly differently for each library.

For fontawesome, do the following. At the top of the file, where

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

add a link somewhere inside the head tag, like this

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css" />
</head>

Now select a category. I will add animals

Then I click on a cat, for example

and copy the tag with the class

Now I insert it into my blocks

<div class="row">
    <div class="block">
        This is where the dog lives 
        <i class="fas fa-dog"></i>
    </div>

    <div class="block" style="flex-grow: 2;">
        <i class="fas fa-cat"></i>
        <i class="fas fa-cat"></i>
        <i class="fas fa-cat"></i>
    </div>

    <div class="block">
        <i class="fas fa-kiwi-bird"></i>
        kiwi house
    </div>
</div>

It will look something like this:

The icons seem very small, so I will add the fa-2x class built into the library, which allows you to increase the size of the icons.

Okay, everything has crawled out of the blocks… Ah, that’s because we clearly specified the height of the block in the class, so let’s remove the height style there.

<style>
    .block {
        border: 1px solid black;
        /* removed height: 1rem;  */
        margin-bottom: 0.5rem;
        flex-grow: 1;
    }
    /* ... */
</style>

Let’s add some white space to them

<style>
    .block {
        border: 1px solid black;
        margin-bottom: 0.5rem;
        ma

## Connecting a third-party library

To make it more fun, I will use icons along with the text.

There is a wonderful library of icons called [fontawesome](https://fontawesome.com/icons?d=gallery&m=free) with a ton of icons for every colour and taste.

To start using it in your file, you need to add a link to its styles. This is done slightly differently for each library. 

For fontawesome, do the following. At the top of the file, where

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

add a link somewhere inside the head tag, like this

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css" />
</head>

Now select a category. I will add animals

Then I click on a cat, for example

and copy the tag with the class

Now I insert it into my blocks

<div class="row">
    <div class="block">
        This is where the dog lives 
        <i class="fas fa-dog"></i>
    </div>

    <div class="block" style="flex-grow: 2;">
        <i class="fas fa-cat"></i>
        <i class="fas fa-cat"></i>
        <i class="fas fa-cat"></i>
    </div>

    <div class="block">
        <i class="fas fa-kiwi-bird"></i>
        kiwi house
    </div>
</div>

It will look something like this:

The icons appear to be quite small, so I will add the fa-2x class built into the library, which allows you to increase the size of the icons.

Okay, something has crawled out of the blocks… Ah, that’s because we clearly specified the block height in the class, so let’s remove the height style there.

<style>
    .block {
        border: 1px solid black;
        /* removed height: 1rem;  */
        margin-bottom: 0.5rem;
        flex-grow: 1;
    }
    /* ... */
</style>

Let’s add some white space to them

<style>
    .block {
        border: 1px solid black;
        margin-bottom: 0.5rem;
        margin: 0.25rem; /* margins around blocks */
        padding: 0.5rem; /* padding inside blocks */
        flex-grow: 1;
    }
    /* ... */
</style>

Everything looks fine now.

Figuring out the width

By the way, I wanted the second block to be twice as wide as the others, but it turns out to be almost smaller than the first block, plus the first and last blocks should be equal.

How is this possible, since we specified flex-grow: 1; there? The thing is, flex-grow tries to distribute the empty space in the blocks without taking into account the space occupied by the content.

The size of the content is determined by the flex-basis style, which by default tries to fit all content into a single line.

To make flex-grow take the content into account, you need to write the property flex-basis: 0

.block {
    border: 1px solid black;
    margin-bottom: 0.5rem;
    margin: 0.25em;
    padding: 0.5em;
    flex-grow: 1;
    flex-basis: 0; /* added */
}

From now on, everything is as specified in flex-grow, the first and last are equal, the second is twice as large

Fixing the block size

Now we have a flexible layout

Imgur

but sometimes we want a block not to respond to stretching. For example, I want the kiwi house to always be a fixed size.

To do this, I can set the flex-grow property to zero. Grow means expand, and if we set it to 0, we are saying don’t expand. Let’s add this style directly to the block

<div class="row">
    <!-- ... -->
    <div class="block" style="flex-grow: 0;">
        <i class="fas fa-2x fa-kiwi-bird"></i>
        kiwi house
    </div>
</div>

Hmm, that kiwi looks really squashed

It’s actually quite interesting here, because the dog and cats are in the correct proportions, but the kiwi is squashed as much as possible so that the cats and dogs take up the maximum possible space.

How can we make things easier for the poor bird? Remember, we specified the flex-basis: 0 property for all blocks so that the stretching would be proportional. So, using this property, we can specify a specific block width, which is essentially the same as width but for flex layout. For example, I’ll put 250px there

<div class="row">
    <!-- ... -->
    <div class="block" style="flex-grow: 0; flex-basis: 250px;">
        <i class="fas fa-2x fa-kiwi-bird"></i>
        kiwi house
    </div>
</div>

And that’s it, now the bird is cooler than everyone else:

But of course, this is overkill. If you just want the bird not to be squashed, simply set the value to auto

<div class="row">
    <!-- ... -->
    <div class="block" style="flex-grow: 0; flex-basis: auto;">
        <i class="fas fa-2x fa-kiwi-bird"></i>
        kiwi house
    </div>
</div>

and then the block will take up exactly as much space as it needs:

In general, we can now add as many rows as we want and prescribe unique behaviour for each block

<div class="row">
    <!-- ... -->
</div>

<!-- added a second row -->
<div class="row">
    <div class="block" style="flex-grow: 3; text-align: centre;">
        <i class="fas fa-2x fa-dog"></i>
        <i class="fas fa-2x fa-dog"></i>
        <i class="fas fa-2x fa-dog"></i>
    </div>

    <div class="block" style="flex-grow: 1; ">
        <i class="fas fa-2x fa-horse"></i>
        horse
    </div>
</div>

That’s how it is.

Task

Layout as shown in the picture

  • All birds (except for the last crow), trees, and frogs should not be rubberised and should take up exactly as much space as they need.
  • Create separate classes for trees and fish to colour the blocks.