Table Of Contents

Coding Notes

CSS Grid

April 26, 2019

Definitions

Grid container - element containing a grid, defined by display: grid; (you can have as many as you want)

Grid item- any direct descendent of a grid container (only first level descendents)

Grid line - horizontal or vertical line separating the grid. Referenced by numbers starting and ending with the outer borders of the grid

Grid cell - intersection between a grid row and a grid column

grid track - the space between two or more adjacent grid lines (row tracks are horizontal, column tracks are vertical) (row or column)

Grid area - rectangular area between four specificed grid lines (grid areas can cover one or more cells)

Grid gap - empty space between grid tracks (shown in blue). Commonly called gutters.


  1. Define a grid
  2. Place items where you want in the grid

Useful Links:

https://goo.gl/SJmlms
https://gridbyexample.com
https://goo.gl/wa0Fk9
https://goo.gl/z01gjF
Https://goo.gl/URouSh
Https://goo.gl/ae838
http://mor10.com/wceu2017


5 - Implicit vs Explicit Tracks

.container {
  display: grid;
  grid-gap: 20px;
  grid-template-columns: 200px 400px;
}

C7A51B92 C4E4 4C20 9518 CAF42F4C05C3

Here we have defined what the columns will be, which is explicit, but we have not defined what the rows will be, which is implicit.

ScreenShot2019 04 25at17 30 08

If we add grid-template-rows: 50px 100px;

7BF327A6 77DC 4EFD 952D ECC0EF41ADBD

And two more grid items, how can we set the size of the implicitly created row?

Using grid-auto-rows

Add grid-auto-rows: 100px 500px; for example

D257A73F DD17 4750 807D E422F19BB80D

There is also grid-auto-columns. However, if we were to add it to this example, it wouldn’t do anything. How do you get extra columns? By default, you define your columns and any extra elements are turned into rows. That is where grid-auto-flow, which instead of automatically giving us rows, it will give us columns.


6 - Grid Auto Flow

When you explicitly define your columns and don’t define any rows, they are automatically created (implicitly).

What grid-auto-flow will do is determine whether to add another row or column if you have another item that is implicitly defined.

grid-auto-flow:row is the default.

A56841C8 AA3C 47A9 AC2F D8308D555A9F

If you do grid-auto-flow:column

EDF1F6A0 B1DD 4592 B68D 2693890CEBB4

The extra item will now be created as a column, instead of a row.


7 - Sizing Tracks

fr unit (fractional unit) -represent the amount of space that is left after all the elements are laid out -css grid will layout the columns that have explicit width/height and then if you said 1fr for example, it will take up the remaining available space

AE8E45C8 36CD 46C7 AF48 F2F6C6D7D3CD

B4297353 7F25 407B AE0F 99AB8FC40EFB

AFE95215 A5DF 49F8 8BE1 A4C291FFF491

NOTE: using fr with grid-template-rows will only work if the grid item has a height.

For grid-template-columns: auto 1fr; the auto portion will adjust to the max size of the contents (the widest content that is defining that column.

5CDB8028 2488 4BFB A25B C441CF558D91

auto sizes to fit the widest content


8 - Repeat Function

grid-template-column: 1fr 1fr 1fr 1 fr; is equal to grid-template-column: repeat(4,1fr)

this is also possible grid-template-column: repeat(4, 1fr 2fr);

Also grid-template-columns: 100px repeat(2, 1fr auto) (see below) 2DEAB63D BFD9 47E9 A71D 1F5E5C1B1C62


EMMETT TRICK

BFCBBD46 6B1A 4FBA B0F7 DE778B43893C .item.item${$}*30 <div class=“item item1”>1</div><div class=“item item2 ”>2</div>etc etc Will expand to: 658753EA 8797 473E B8CE 27BA2072976F


9- Sizing Grid Items

spanning allows you to tell some items to be a specific width.

grid-column: span 2; will allow the item to take up two spots in the grid

8E0294FD D937 49D5 8F43 3C4B0D042F3F

span will layout one after the other, so if there is not enough space it will go to the next row like so :

1C2E5CD6 D1E0 4B6F ADE7 57776ED775F6

If we want to span multiple rows, we can you do, grid-row:span 2;

D8B406FD 792F 4BCD ADF8 29AE01E6470C

If you span wider than the number of columns, for example if we have 6 spots in the grid but you make it grid-column: span 10; it will force the grid to be larger than it wants (see below)

56425F65 71B6 4356 ACF1 AD72A685D62D


10 - Placing Grid Items

grid-column is actually a short hand. if you did grid-colum: span 2; it is actually grid-column-start:span 2; grid-column-end:auto

8FB461B8 EFCE 4A92 8E21 42075D06FBFB

If you were to take an item in the grid and say: grid-column-start: 2 then it would start on the number 2 track like so..

A8A2CB10 92CA 46D8 B1E3 BD54F9C086F9

If you also added grid-column-end:5; it would span it to track 5; DBEE5C5B E465 42B9 80D9 1067C445292C

Short hand for colum-end and column-start is grid-column: 2/5

You can also combine them with spans

BE27082A 40A1 4D3D 8373 8849013B9754

You could say start at 1 and span 2 with this syntax: grid-column: 1 / span 2;

1960FEB9 57A3 451A 98BB EAD1A23E8F5E

You can also tell it to end at the last track. If you do not know how many tracks there are you can put -1

grid-column: 1 / -1; this can be used as width 100%

F848FB9F 7439 42C7 96CD CEBC1E6A5D70

(If you do -2, it would put it at the second track from the end)

For rows, you cannot do -1 to do the row end, unless you have explicitly stated the rows, and if you have explicitly stated the rows it will only go to the end of the explicit track.

CF3EDA93 8318 45F7 B55B ED20A13E8578

The example below will only do the first one because we have not explicitly defined any rows. 64D63AC6 28C1 4152 9678 55E2B30A6149


11- Spanning and Placing Cardio

 <div class="container">
      <div class="item item1">1</div>
      <div class="item item2">2</div>
      <div class="item item3">3</div>
      <div class="item item4">4</div>
      <div class="item item5">5</div>
      <div class="item item6">6</div>
      <div class="item item7">7</div>
      <div class="item item8">8</div>
      <div class="item poop">💩</div>
      <div class="item item9">9</div>
      <div class="item item10">10</div>
      <div class="item item11">11</div>
      <div class="item item12">12</div>
      <div class="item item13">13</div>
      <div class="item item14">14</div>
      <div class="item item15">15</div>
      <div class="item item16">16</div>
      <div class="item item17">17</div>
      <div class="item item18">18</div>
      <div class="item item19">19</div>
      <div class="item item20">20</div>
      <div class="item item21">21</div>
      <div class="item item22">22</div>
      <div class="item item23">23</div>
      <div class="item item24">24</div>
      <div class="item item25">25</div>
      <div class="item item26">26</div>
      <div class="item item27">27</div>
      <div class="item item28">28</div>
      <div class="item item29">29</div>
      <div class="item item30">30</div>
    </div>

    <style>
      .container {
        display: grid;
        grid-gap: 20px;
        grid-template-columns: repeat(5, 1fr 2fr);
        grid-template-rows: repeat(10, 50px);
        /* Make the grid 10 columns wide, every other taking up twice the free space */
        /* Make the grid have 10 explicit rows, 50px high each */
      }

      /* With Item 1, start at col 3 and go until 5 */
      .item1 {
        grid-column: 3/ 5;
      }
      /* With Item 2, start at col 5 and go until the end */
      .item2 {
        grid-column : 5/-1;
      }
      /* Make Item 5 double span 2 cols and rows */
      .item5 {
        grid-column: span 2;
        grid-row: span 2;
      }

      /* Make Item 8 two rows high */
      .item8 {
        grid-row: span 2;
      }

      /* Make Item 15 span the entire grid width */
      .item15 {
        grid-column: 1/-1;
      }
      /* Make item 18 span 4 widths, but end 9 */
      .item18 {
        grid-column: span 4/ 9;
      }

      /* Make item 20 start at row 4 and go for 3 */
      .item20 {
        grid-row: 4 / span 3;
      }
    </style>

8443D8C0 7174 497B 8E04 3B55C0B46091


12 - Grid Auto-Fit and Auto-Fill

Starting point 01734CE6 BF8D 45A9 97A1 7A51EC85A460

 <style>
    .container {
      display: grid;
      grid-gap: 20px;
      border: 10px solid var(—yellow);
    }
  </style>

Instead of doing: grid-template-columns: repeat(5, 100px); A98839F8 AAF5 48D0 AF18 2ACD0AA0EFCE

Which you won’t know how many columns will fit and the content of the items might be bigger or smaller. We have keywords like auto-fill and auto-fit.

grid-template-columns: repeat(auto-fill, 150px) -> E857C097 B57E 478D 9416 94671F29E63E

For AutoFill, you don’t tell it how many columns you want, you just say you figure out how many could possibly fit.

As you resize the screen, it will flow differently.

What is the difference with grid-auto-fit. Vs fill.

The difference is when you don’t have enough items to fill up the entire width or height of a grid.

When you have fill on, it will chop it up into as many spaces as it can. 00B575D1 6DF7 445C 93EF 50916560DB4E

At the right edge, there is space for two more items.

However with auto-fit, it would actually end the grid at the last item.

9209AB42 0C3F 4A65 B3BA A5516D370F91

Why is that helpful?

Let’s say you have a bunch of buttons and you want them left aligned except you want one on the right.

You can take the item you want to put the right, and do ->

.item4 {
  grid-column: auto/ -1;
}

9F568FF0 8DE1 4704 A998 D7A7A6829EF1

You could also do .item4{ grid-column-end:-1}

If we change it from fill to fit, there is no way to tack it onto the end because the grid ends.


13 - MinMax

<div class="“container”">
  <div class="“item" item1”>Item 01</div>
  <div class="“item" item2”>Bonjour!</div>
  <div class="“item" item3”>Item 03</div>
  <div class="“item" item4”>Item 04</div>
</div>

<style>
  .container {
    display: grid;
    grid-gap: 20px;
    border: 10px solid var(—yellow);
    grid-template-columns: repeat(auto-fill, 150px);
  }
</style>

70C57E6C DB40 49E8 B7A9 E7AAA0C24D68

If we were to change css to -> grid-template-columns: repeat(auto-fill, 100px); we run into the issue where the content spills out like so ->

07D85E88 1181 468C 959B 22CAB4EDA86C

We don’t want to have to figure out how wide our columns should be, they should just flow as wide as they need to be.

We can replace that with a minmax(), which we pass the minimum and maximum that the track can be. min(150px, 1fr) meaning that at a max they will be the entire width of the grid.

If you change it from auto-fill to auto-fit it will function like this ->

It will not give us that extra space, it will stretch the items inside of the track to fit.

We will be using that often in real world examples.

.container {
  display: grid;
  grid-gap: 20px;
  border: 10px solid var(--yellow);
  /* grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); */
  grid-template-columns: 150px 150px 150px 150px;
}

Will give you ->

A430FAAA E853 4558 B2B9 B97CD61F8F5E

If you change it to -> grid-template-columns: auto 150px 150px 150px; ->

AFD6BE35 EC47 4C8A 81F9 F9336FDCACD3 If you resize it , it will get smaller

4F19E730 8DF3 4B6F 9123 9903728D7BD4

NTS: tried swapping auto with 1fr and it worked similarly

You can also use the fit-content function instead of auto because you might think auto is a bit big. You pass fit-content a clamp value, a max width or height that it cannot surpass.

grid-template-column: fit-content(100px) 150px 150px 150px;

B5F14011 4E23 4C7B 82F7 92DA24212991


14 - Grid Template Areas

<div class="container">
  <div class="item item1">
    <p>I'm Sidebar #1</p>
  </div>
  <div class="item item2">
    <p>
      Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore, sed.
    </p>
    <p>Lorem ipsum d</p>
  </div>
  <div class="item item3">
    <p>I'm Sidebar #2</p>
  </div>
  <div class="item footer">
    <p>I'm the footer</p>
  </div>
</div>

<style>
  .container {
    display: grid;
    grid-gap: 20px;
  }
</style>

BA334120 B7FE 4D5E 81DA B768E48B05FF

We want to lay it out with one sidebar on the left, content in the middle, another sidebar on the right and then the footer along the bottom.

We are going to do grid-template-columns:1fr 500px 1fr which will put the content at a fixed width and the sidebars fill the rest of the size ->

A5FC7662 13A1 490A B532 A651A349044D

Add grid-template-rows: 150px 150px 150px;

0AD4A7F0 81C5 4B13 BA83 23D1EEF2DE78

We want the footer to span the last row, and the sidebar 1 and sidebar 2 and content area span two rows.

We are going to create template areas. You write and for each row you give yourself a set of quotes and type the name of the area that you wish it to be.

grid-template-areas: "sidebar-1 content sidebar-2"

Gives you ->

507D6770 E3AD 4AB1 850A 32F15E0C3B95

grid-template-areas:
  “sidebar-1 content sidebar-2”
  “sidebar-1 content sidebar-2”
  “footer footer footer”;

7685BED9 8D41 4FF8 BC4F E2CF889F7FFD

Now when we want to place our items in the areas, we can use the names.

.footer {
  grid-area: footer;
}

.item1 {
  grid-area: sidebar-1;
}

.item2 {
  grid-area: content;
}
.item3 {
  grid-area: sidebar-2;
}

35E318DF F427 4D22 92D2 D6406C1EB93B

We can use media queries to refine the template areas as we need them.

2ECE53D2 49DF 4711 80C7 434A607804DB

@media (max-width: 700px) {
  .container {
    grid-template-areas:
      “content content content”
      “sidebar-1 sidebar-1 sidebar-2”
      “footer footer footer”;
  }
}

This way, even if you add more columns,

Grid Line Names

When you create grid areas, you also get access to grid line names.

We aren’t going to define columns and rows.

86D12C22 AC5B 43B5 B705 227C19CB9EB1

If you add

.container {
  display: grid;
  grid-gap: 20px;
  grid-template-areas:
    "💩 💩 💩 💩 🍔 🍔 🍔 🍔"
    "💩 💩 💩 💩 🍔 🍔 🍔 🍔"
    "💩 💩 💩 💩 🍔 🍔 🍔 🍔"
    "💩 💩 💩 💩 🍔 🍔 🍔 🍔";
}

86C0B8A1 23D6 4027 8A85 F8DA3B369F9D

If you add

.item3 {
  grid-area: 💩;
}

E56A1B0E 2905 47E1 94B6 F5EAB525AE39

You can see that new implicit rows are created.

Before we were doing

.item3 {
  grid-column: 2 /5;
}

Which would tell it to start at 2.and span till 5. With template areas we can use line names like 💩-start / 💩-end.

D51B5A6B 8732 4BFA 918D 6566B4CF0CEA

Or

.item3 {
  grid-column: 💩-start/🍔-end;
}

15- Naming Lines

When you set grid-template-areas, you get line names for free but if you would like to name your lines specific names, you can do that.

Starting point -> We have 10 rows that autosize and then after that they turn into implicit.

ADAE382E BDD8 46D9 A09F 78B4BF67AE5F

The way you name your lines is by defining them in square brackets when you define your columns and rows. Then you can call them like so ->

.container {
  display: grid;
  grid-gap: 20px;
  grid-template-columns: [site-left] 1fr [content-start] 500px [content-end] 1fr [site-right];
  grid-template-rows: [content-top] repeat(10, auto) [content-bottom];
}

.item3 {
  background: slateblue;
  grid-column: content-start;
  grid-row: content-top/ content-bottom;
}

Which still gives you the same effect ->

609C9ACB 6FF6 4ABF 8F4A 28C4AFBF6FA8

You can also name lines two things like so ->

grid-template-columns: [sidebar-start site-left] 1fr [sidebar-end content-start] 500px [content-end] 1fr [site-right];


16 - Grid Auto Flow Dense

When you have more items than can fit in a grid, by default it will wrap onto the new lines and create an implicit row .We can switch that to column meeting it creates implicit columns.

In this example, we start with 70 items, and we will make a grid of 10 equal items.

.container {
  display: grid;
  grid-gap: 20px;
  grid-template-columns: repeat(10, 1fr);
}

3F5C0B38 BAB3 418D 9AD8 690B6C975400

For every 6th item, we are going to make it span 6 items and make it blue.

6103A9A5 B0AB 427A AEB7 B10EEE2C5E72

.item:nth-child(6n) {
  background: cornflowerblue;
  grid-column: span 6;
}

The way the browser lays out the grid, it takes all the spots we have (10 across) and takes each item and checks if it can fit it and if it can, it places it. When it gets to the 6th item, we know it needs to take up 6 spots, but we only have 5, so it breaks onto the next row and we continue adding that item. The downside is it doesn’t fill in the empty spots with items that could fit like 7,8,9,10

0815D9C6 2489 42C2 BCDF 930DE445C069

If you add grid-auto-flow:dense; -> 4FC8C9BB FFD4 40F4 B60B 72A8C4A5D8F6

How that works is when the browser hits 6, it knows it cannot fit it so it puts it on the next line. Then it gets to 7 and goes back to the start and says is there anywhere I can fit this one in. It will go back to the first available grid column or row that we have and fit it in.

We will make a few more items irregularly shaped ->

.item:nth-child(8n) {
  background: tomato;
  grid-column: span 2;
}
.item:nth-child(9n) {
  grid-row: span 2;
}

If you don’t care which order they show up in, it will try and fit all the different values that you want.

.container {
  display: grid;
  grid-gap: 20px;
  grid-template-columns: repeat(10, 1fr);
  grid-auto-flow: dense;
}
.item:nth-child(6n) {
  background: cornflowerblue;
  grid-column: span 6;
}
.item:nth-child(8n) {
  background: tomato;
  grid-column: span 2;
}
.item:nth-child(9n) {
  grid-row: span 2;
}

B478FF0C 7E5E 46BD B374 1416BA6ED040

If you add

.item18 {
  background: greenyellow !important;
  grid-column-end: -1 !important;
}

Grid will first layout the ones that need to go in a specific spot first, and then fill them in. You won’t always get a perfect layout if there are no items that are the right size to fit the empty spaces.


17- Grid Alignment + Centering

Even if you are not building a website that requires a strict grid, it may be that your grid is one column wide and two rows high , it is still useful to use css grid for centering things.

There are 6 properties you can use to align things in css grid.

justify-items: align-items:

justify-content: align-content:

align-self: justify-self:

The justify properties are along the x (row) axis and align items are along the y or column axis. Unlike flex box, grid doesn’t switch axis.

A Complete Guide to Grid | CSS-Tricks

We are starting with 40 items on the page.

justify-items and align-items refers to the items themselves, which are direct children of the grid container.

Justify Items

The default of justify-items is stretch, which will stretch them across the entire grid.

BB1CD748 9E70 46D7 995E 904F9B9C2F60

If you change to justify-items:center like so

.container {
  display: grid;
  grid-gap: 20px;
  grid-template-columns: repeat(10, 1fr);
  justify-items: center;
}

You get -> 53715E63 AF52 4761 AD82 F3D7D9D93AEB

For center, it will only go as wide as the content inside of it.

There is also justify-items: start and justify-items:end

Start -> 0DF921A3 AEB7 40AA 8EDB 8410D80AEF7A

End -> 9AE428E8 4E80 4AF2 B337 A1660C08579A

You can use start or flex-start and end or flex-end, they do the same thing.

Align Items

If we add align-items:start it doesn’t do anything because our rows don’t have any height.

If we add ->

grid-template-rows: repeat(5, 100px);
justify-items: end;
align-items: start;

You get -> E2776B93 BDA9 4D0E AB17 8DD01F245961

align-items:end; will bring them to the end ->

33E0EACE 8581 4606 83F6 CA9364E56B06

align-items:center ->

462DC0EF 28AB 4B9E 9403 8231A2951791

align-items:stretch ->

114E093B B0DF 49D5 9EBF C124BA6D46F2

To perfectly centre something you can just do

justify-items: center;
align-items: center;

There is also a css shorthand we can use -> but browser support is iffy

place-items: center center;

Justify-Content & Align-Content

If the grid is not as wide as we could possibly want, (we are using fr units which means we will go all the way across but if we were to change that to 100px, we would have extra space.

2315E13D 6C41 4CB1 AF4F A09263A67FD7

We have all that extra space. What we do with that extra space is what justify-items and align-items are responsible for.

justify-content:end ->

0306151E 227A 4D9F B526 C531CE35A673

justify-content:center ->

0FB2F1EB 85F4 4F03 A8C6 67F970251F74

The two most helpful ones are space-around and space-between

justify-content:space-around ->

5860B161 285B 4A52 928B 43CD745BCB41

The spaces aren’t even because space-around will take all of the extra space and evenly divide it on either side of the column. If you don’t want the sideline parts, we can do space-between

AC4F3856 FE66 44DC 918B F8ADB4C7F4EC

If your container is bigger than you need your grid to be (this won’t be the case if you are using % or fr units), you can use justify-content to tell it where those items should go.

If our container had a hard height on it, like 500px, what will happen is those items stretched h by default.

We can however do align-items: start align-items: end align-items:stretch (default) align-items: space-around align-items: space-between

Align Self and Justify Self

Allows us to overwrite each of those on a case by case basis (on the item).

.container {
  display: grid;
  grid-gap: 20px;
  grid-template-columns: repeat(5, 130px);
  place-items: center center;
  justify-content: space-between;
  align-content: space-between;
}
.itm {
  background: white;
}

.itm5 {
  justify-self: center;
}

E0AA16FD 7CF3 4A0E AEA4 0B02878EDC45

Wes uses this often to center his text.

4CC62ADB 7B66 4477 94A9 4FF6153BACD0

.item {
  display: grid;
  justify-content: center;
  align-items: center;
}

^ Will perfectly center something.

18 - Re-ordering Grid Items

There is an order property that allows you to place grid items.

Starting example with ->

    <div class="container">
      <div class="item logo">LOGO</div>
      <div class="item nav">NAV</div>
      <div class="item content">
        <p>I'm the Content!</p>
      </div>
    </div>

    <style>
      .container {
        display: grid;
        grid-gap: 20px;

060479D9 9F78 4DA6 B666 A0853393F7DC

We are going to make a grid of 10 items, equal size, and make the content go all the way across ->

 .container {
        display: grid;
        grid-gap: 20px;
        grid-template-columns: repeat(10, 1fr);
      }

      .content {
        grid-column: 1/ -1;
      }

0B18F3D8 A39D 47AA BDBE 3AE31342693B

We want the logo to span 2, and the nav span 8. ->

.logo {
  grid-column: span 2;
  order: 2;
}
.nav {
  grid-column: span 8;
  order: 1;
}

-> 1C0ECE92 95F6 4C31 A2DD DB0A8C7D7E23

What if we wanted to put the nav before the logo at a smaller screen size.

You can give your items an order property.

If you put -> .logo{order:1;} that will put it at the end because the default value is 0.

      .logo {
        grid-column: span 2;
        order: 2;
      }
      .nav {
        grid-column: span 8;
        order: 1;
      }

      .content {
        grid-column: 1 / -1;
        order: 3;
      }

The reordering will screw up select and accessibility. Even though the source order (logo, nav, content) and then goes , logo, nav, content, it will mess up the screenreader. Don’t rearrange a paragraph tag into a different order just with css because it won’t get read back.

It screws up highlighting of text ->


19 - Nesting Grid Items

We will be creating an album layout. It will teach us how to nest grid and give us practice with auto fit and min max.

This example will be fully responsive without having to write any media queries.

Starting HTML ->

<div class="albums">
  <div class="album">
    <img
      class="album__artwork"
      src="https://source.unsplash.com/random/300x300?v=1"
    />
    <div class="album__details">
      <h2>Album Title</h2>
      <p class="album__artist">Artist Name</p>
      <p class="album__desc">
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsum sed sint
        doloremque repellat, iste debitis.
      </p>
      <p class="album__desc">
        Lorem ipsum dolor sit amet consectetur, adipisicing elit. Facilis,
        excepturi!
      </p>
    </div>
  </div>
  <div class="album">
    ...
  </div>
</div>

7FC18E2D 0843 4743 BBBF E36B218E63AB

Albums will be our grid, album will be our grid item.

I thought we would do it like so ->

   .albums {
        display: grid;
        grid-template-columns: 1fr 1 fr 1fr;
      }

But we actually want to use auto-fit and pass it 100px instead of fr.

grid-template-columns: repeat(auto-fit, 100px);

However that doesn’t work well, so we need to use minmax. At minimum we want it to be 400px, and at max 1fr.

grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));

Now we will style the album a bit.

.albums {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
  grid-gap: 20px;
}

.album {
  background: rgba(255, 255, 255, 0.1);
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
  padding: 20px;
}

How do we get the image and text to go side by side? If albums is the grid, and album is the grid item, how do I use grid on the actual element itself.

Grid items can also be grids (just like in flex-box flex items can also be flex containers).

Add display;grid to .album and make two columns. One that is 150px wide for the image, and then the rest for the description.

.album {
  background: rgba(255, 255, 255, 0 2);
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
  padding: 20px;
  display: grid;
  grid-template-columns: 150px 1fr;
  grid-gap: 10px;
}

DA8513A1 9886 49D8 8199 C77E08327E9E

However the image wasn’t adhering to 150px..

Because the natural image height is 300px, it is causing it to be bigger than it should be. We can fix that with the code below so it spans the entire width of it’s column.

.album__artwork {
  width: 100%;
}

That forces the image to size itself based on the available space for it (150px) and that will automatically resize the height.

20EE487D 6DDE 495C 972A D53E4098498F


We are going to be making an image gallery, and as wide as the screen sizes, the images fit using grid-auto-flow: dense.

The idea about the image gallery is not everything fits into each other perfectly.

How Wes is doing it is he is making all of those possible sizes, all based on a 100px grid. The grid will always be 100px by 100px, and each of the images is going to span a random about (between 1 wide and 4 wide and 1 high and 4 high). That will be totally random.

By having a lot of extra little 1 by 1s, it will hopefully fill all the gaps.

The small images are fillers.

For this example, we have our gallery which will be our grid. It’s empty because instead of manually coding all the sizes by hand, we are going to use javascript to generate them. In the images folder there are images all 500px by 500px. We will be using css property called object fit in order to make them fit perfectly. Sort of like background-size: cover;

First, we generate gallery images.

We need a function which will generate some HTML based on passed in widths and heights between 1 and 4 width (horizontal), and 1 and 4 height (vertical). In our CSS we will assign a class of h1 and v1 and those correspond with a different span value.

AA616DEE FB14 4DE5 9BDC 9C1611A11C5F

We want to create a helper function which will help us generate a number between 1 and something.

  <script>
      const gallery = document.querySelector(".gallery");
      const overlay = document.querySelector(".overlay");

      const overlayImage = overlay.querySelector("img");
      const overlayClose = overlay.querySelector(".close");

      function generateHTML([h, v]) {
        return `
        <div class="item h${h} v${v}">
        <img src="images/${randomNumber(12)}.jpg">
        <div class="item__overlay">
        <button>View →</button>
        </div>
        `;
      }

      function randomNumber(limit) {
        return Math.floor(Math.random() * limit) + 1;
      }
    </script>

Now we want an array of arrays with different height / width values.

;[[1, 4][(2, 2)][(4, 1)]]

First value is how many columns it spans and the second is how many rows.

We want to make an empty array with 50 spots. You do that like so. Array.from also gives us access to the map function which allows us to populate what goes into each one of those. ->

const digits = Array.from({ length: 50 }, () => [
  randomNumber(4),
  randomNumber(4),
])

When we load the page, we get an array of arrays. We want to map over each item in the array and generate array of html strings and then join those for one large HTML string which we will set to galleries innerHTML.

      const gallery = document.querySelector(.gallery”);
      const overlay = document.querySelector(.overlay”);

      const overlayImage = overlay.querySelector(“img”);
      const overlayClose = overlay.querySelector(.close”);

      function generateHTML([h, v]) {
        return `
        <div class=“item h${h} v${v}”>
        <img src=“images/${randomNumber(12)}.jpg”>
        <div class=“item__overlay”>
        <button>View →</button>
        </div>
        `;
      }

      function randomNumber(limit) {
        return Math.floor(Math.random() * limit) + 1;
      }

      const digits = Array.from({ length: 50 }, () => [
        randomNumber(4),
        randomNumber(4)
      ]);
      console.log(digits);

      const html = digits.map(generateHTML).join(“”);
      gallery.innerHTML = html;

Now we make gallery a grid. We need to make it 100px wide for each one. How many do we need? We don’t know so we can use repeat and auto-fill.

Add ->

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, 100px);
}

C8DDB92B 477F 4D5B AE9E F8A289009D2C

For vertical, we don’t know how many there will be, so we will just size the implicit rows with grid-auto-rows: 100px

35E39060 3DA4 4544 95A3 BA45EB99E995

Any item with .v2 wi will add a grid row span of two like so ->

.item.v2 {
  grid-row: span 2;
}
.item {
  overflow: hidden;
}

-> 40502C01 838B 47E4 8127 D1768947AF5A

.item.v2 {
  grid-row: span 2;
}

.item.v3 {
  grid-row: span 4;
}

.item.v4 {
  grid-row: span 4;
}

.item.h2 {
  grid-column: span 2;
}

.item.h3 {
  grid-column: span 4;
}

.item.h4 {
  grid-column: span 4;
}

9F7EEEC4 4EDB 4DA8 AC30 30718E031441

The problem now is we have all these empty spaces.

Add grid-auto-flow:dense to .gallery grid container ->

F6904B64 7AB7 4074 8D00 D0E79F084AE1

Now we are going to go to our javascript and add a bunch of 1 by 1 fillers to take up the empty spaces. We are just going to concat a bunch of 1 by 1s.

const digits = Array.from({ length: 50 }, () => [
  randomNumber(4),
  randomNumber(4),
]).concat([
  [1, 1],
  [1, 1],
  [1, 1],
  [1, 1],
  [1, 1],
  [1, 1],
  [1, 1],
  [1, 1],
  [1, 1],
  [1, 1],
  [1, 1],
  [1, 1],
  [1, 1],
  [1, 1],
  [1, 1],
  [1, 1],
  [1, 1],
  [1, 1],
])

Next we are going to work on the overlay. We are going to make each grid item a 1 by 1 grid

.item {
        overflow: hidden;
        display: grid;
        grid-template-columns: 1;
        grid-template-rows: 1;
      }

CSS Grid is also really good for overlapping items. We can use it instead of position absolute.

   .item img {
        grid-column: 1/-1;
        grid-row: 1/-1;
        width: 100%;
        height: 100%;
      }

That gives us ->

91F9BB00 5646 41D8 9CFF 4DE792C50F8B

The images are now being stretched and what we can do about that is use object-fit:cover which will trim the top or the bottom or left or right to fit perfectly while showing as much of the image. -> 9F47C69A 76A3 4126 9E60 1005F624EBB5

For the details, we grab the .item__overlay. The overlay is sort of below the actual item, and we want it to overlap the actual image. We have not done the ability to overlap objects. We want to take the grid-column and grid-row from .item img and apply it to the details.

If you place them on the same row and column, you can overlap items and then z-index comes into place.

      .item__overlay {
        background: #ffc60032;
        grid-column: 1/-1;
        grid-row: 1/-1;
        position: relative;
		display: grid;
}

->

FB358E9D 24AA 4AF0 AB09 68BEDB20668E

We add the following to align it in the center ->

justify-items: center;
align-items: center;

B6D52C2E EEEB 4517 A222 437E06240280

We want to move the view button off the item using transform:translateY(100%) which moves the button off.

When the item is hovered, we will put it back.

.item img {
        grid-column: 1/-1;
        grid-row: 1/-1;
        width: 100%;
        height: 100%;
        object-fit: cover;
      }

      .item__overlay {
        background: #ffc60032;
        grid-column: 1/-1;
        grid-row: 1/-1;
        position: relative;
        display: grid;
        justify-items: center;
        align-items: center;
        transform: translateY(100%);
      }

      .item__overlay button {
        background: none;
        border: 2px solid white;
        color: white;
        text-transform: uppercase;
        background: rgba(0, 0, 0, 0.7));
        padding: 5px;
      }

      .item:hover .item__overlay{
        transform: translateY(0)
      }

Now we need to add the overlay on button click. We will add the event listener after all the items have been created so we don’t have to deal with event delegation.

const items = document.querySelectorAll(".item")
items.forEach(item => item.addEventListener("click", handleClick))
      function handleClick(e) {
        console.log(e.currentTarget);
        const src = e.currentTarget.querySelector(“img”).src;
        overlayImage.src = src;
        overlay.classList.add("open");
      }

We already have this css ->

.overlay {
  position: fixed;
  background: rgba(0, 0, 0, 0.7);
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  display: none;
  z-index: 2;
}

.overlay.open {
  display: grid;
}

Add js for the close overlay button ->

 function close() {
        overlay.classList.remove("open");
      }
   overlayClose.addEventListener(“click”, close);`

21 - Flexbox vs Grid

Answering questions like when do you use one over the other, are they replacements, do they go together, can you use them together?

We will go through 8-9 UI patterns and discuss how to implement them in grid or flex box.

In general grid can do everything that flex box can do. Some people think flex box is for one dimensional (laying things on X or Y axis) and grid is multi-dimensional (laying things down on an X and Y grid). However, you can also use grid to just align things on an X or Y axis.

One big benefit of flexbox is they can be transitioned meaning if you want to animate a flex grow value with flex box you can but for css grid you cannot.

Pros for grid is it’s much more consistent across all web browsers and not as many bugs as flex box. If you are designing something on a single axis and then you want to wrap that into multiple rows, you can easily do that with CSS Grid.

Examples coming up will show how to achieve things we have done with flex box with grid, and then some examples that only flex box can achieve

Example 1 - Axis Flipping

With FlexBox you can flip axis from column to row and back.

We are going to do this with css grid.

When you click the “flip” button, it will add the class .flip to the .flipper.

Along the x axis you can achieve the same with grid like so->

.flipper {
  display: grid;
  grid-gap: 20px;
  grid-template-columns: repeat(auto-fit, minmax(50px, 1fr));
}

And then to make it along the Y axis, add this code ->

 .flipper.flip {
        grid-template-columns: 1fr;
      }

Now the the functionality works the same as it would with flex box.

Flexbox has the ability to do row-reverse and column reverse but grid does not have that functionality.

Example 2 - Controls on Right

2AC7B98A E32C 49B8 B7F6 8B97BD44E398

Instead of assuming there are three buttons, we don’t want to do that (with flex box you can just apply a flex 1 to that and it would fit it up.

Starting point ->

<div class="tracks">
  <div class="track">
    <h2>The Future (Ft. The R.O.C.)</h2>
    <button></button>
    <button>❤️</button>
    <button></button>
  </div>
  ...
</div>

F22774CF 97A9 4662 B8DE B82A1BDBAD45

We are going to make a one column grid. If you add ->

.track {
  background: white;
  padding: 10px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.1);
  display: grid;
  grid-template-columns: 1fr;
}

Gives you ->

405282F3 984D 43F7 A82C CE173981329F

The problem now is our additional items are being added as rows instead of to the right. We can change that with grid-auto-flow:column;

960E375A 5C68 43A1 89F2 FEFD1023CEA9

If you increase the amount of buttons, they will nicely stack up to the right.

Example 3 - Flex on Item

We want to achieve -> CD48AE8D 9340 4C1C 8055 8A38A09A3DA6

Starting point ->

<div class="controls">
    <button>⏯️</button>
    <button>🐢</button>
    <button>🐰</button>
    <div class="scrubber"></div>
    <button>💬</button>
    <button>🔽</button>
  </div>

  <style>
    .controls {
      margin: 200px 0;
    }

    .scrubber {
      background: #BADA55;
      height: 10px;
      min-width: 100px;
      border-radius: 10px;
    }
  </style>

560A4EA0 32D9 4019 82C4 D9B8796207F8

Wes likes to do this by letting the buttons take up as much space as they need. Whatever we have left (the scrubber) will take up the rest of the value so when you resize the scrubber changes size.

Wes prefers flex box for this.

Add display:flex to .controls

2B43937C 4DE5 4E73 A10B 107DFE928E64

Scrubber has min-width of 100px, but we want it to take up the rest of the space.

We go to the scrubber and add flex:1 that will flex-grow it to take up the rest of the space.

664C97ED C443 4E7D A4A2 7C926D67D64A

If you add align-items:center; to .controls it will center it.

8BEC82E8 36FB 4C35 B47D CB63554B24F9

To do this with grid, we would (comment out all flexbox stuff) ->

    .controls {
        margin: 200px 0;
        /* display: flex; */
        /* align-items: center; */
        display: grid;
        grid-template-columns: auto auto auto 1fr auto auto;
      }

We do auto auto auto 1fr auto auto; because we want the buttons to be equal sizes and the scrubber to take up the rest of the space.

The makes it brittle because if we change the number of buttons, that would cause on of the buttons to get bigger rather than the scrubber.

Being able to apply the flex directly to the element is better because if the number of your flex container changes, you aren’t screwed.

Example 4 - Perfectly centred

Goal -> F6362646 ADEF 40B6 AA60 27509BECF71A

Starting point ->

<div class="hero">
  <h2>Something Big Is Coming</h2>
  <p>Get Ready...</p>
</div>

<style>
  .hero {
    height: 200px;
    background: rgba(255, 255, 255, 0.2);
  }
</style>

2C2E4DCA AE55 44BD 9C08 0D4AB0367A27

Flex

Add display:flex to .hero which turns it into rows ->

62680D15 7DB4 4652 B104 C1E5B78B290E

We need to change the flex directlion to columns like so ->

 .hero {
        height: 200px;
        background: rgba(255, 255, 255, 0.2);
        display: flex;
        flex-direction: column;
      }

79D1F57B 1612 4493 9290 05A36AE19C98

If you add justify-content: center ->

036D5DAA 4092 4769 99AD 8EEA01BCA2B0

Add align-items:center ->

CE99A706 971C 45AB 80F1 269EB683B4EC

Grid

For grid, we will add display:grid ->

AA775318 1EA4 488C 9CBC 1EEF7BB31840

Add justify-items:center ->

BD70ECBA 34F4 4D72 AC72 EBA023A2C410

Add align-items:center ->

55A847F9 0756 44CE B4B6 EBCB25B89B9E

We don’t wan them to be far apart, we want them perfectly centered so we need to do align-content:center; -> 65D6F924 7EEF 4D82 B54B 1FC6B9E98467 -> Now the rows themselves are not stretching, they will be just as big as the content needs to be.

Example 5 - Self Control

Goal ->

D32ADEA5 625B 41EB BA8E 4297180CBC43

Starting ->

<div class="corners">
  <div class="corner item">1</div>
  <div class="corner item">TWO</div>
  <div class="corner item">3</div>
  <div class="corner item">4</div>
</div>

<style>
  .corners {
    display: grid;
    height: 200px;
    width: 200px;
    border: 10px solid var(--yellow);
  }

  .corner:nth-child(1),
  .corner:nth-child(2) {
  }

  .corner:nth-child(1),
  .corner:nth-child(3) {
  }
</style>

4ECA3D79 3788 4E09 A197 043702EF040B

This one is only possible in grid. Probably not a real world scenario but shows the benefit of having the justify-self and align-self values.

We will make a 2x2 grid.

Add to .corners ->

grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;

Or use shortcut grid-template: 1fr 1fr/ 1fr 1fr; which is the exact same thing.

Now we want to put them in the top right hand corner. By default they are stretching .

Add align-items:end ->

90D6F434 CAD6 4720 8A9B 90E42F1CEBA4

Add justify-items: end ->

DBE3414C 0E55 41FE A083 5C383EB44046

That puts each of them in their bottom righthand corner.

Now we want to override it for the 1st one and the second one (we want to stick them to the top) and for the 1st and 3rd we want to stick them to the left.

Add ->

.corner:nth-child(1),
.corner:nth-child(2) {
  align-self: start;
}

.corner:nth-child(1),
.corner:nth-child(3) {
  justify-self: start;
}

1A971628 8230 4BD9 BE25 9FAF7629A7FC

Example 6 - Stacked Layout

This one is only do-able in flex box.

Goal -> F2021680 8129 43A6 9BB7 1AE7A7CAA5EF

Starting ->

<div class="stacked">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
</div>

<style>
  .stacked {
  }

  .stacked > * {
    width: 30%;
    margin-bottom: 20px;
  }
</style>

F22D30A8 B3F6 4A54 BD12 06B0518CDFFD

With grid, your columns are rigid, you can’t have rows that are different sizes. If you wanted to achieve something like this, you would have to do manual spanning across all of the items.

Add display:flex; to .stacked

4795D07C 4701 4341 AD34 22C08673422E

We have made them width:30%; so they should be able to wrap.
Add flex-wrap:wrap ->

B244B616 9EFA 431F A118 F8DBD344A907

If you add justify-content: space-around ->

BB252888 AD0B 4150 A578 7C6DF44D4899

One downside is there is no concept of gap in flex box.

Example 7 - Unknown Content Size

When you don’t know how wide something is but you want to put it in the middle.

Goal -> 293E03FD 6EBA 4635 B941 06A9AF435149

Starting point ->

!— Known Columns, Unknown Content Width —>

  <div class=“container known”>
    <div class=“item”>Short</div>
    <div class=“item”>Longerrrrrr</div>
    <div class=“item”>
      <img src=“https://source.unsplash.com/300x200” alt=“”>
    </div>
    <div class=“item”>💩</div>
  </div>

  <style>
    .known {
      margin: 100px 0;
    }
  </style>

275742E5 CF05 4C0E 9F29 70BBD99B22B4

Grid

Add display:grid to .known

We do know how many columns we have in this case.

Add grid-template-columns: repeat(5, auto); We make them auto because it will autosize the based on the content -> 55088085 79EF 4E37 9E1C 1915D3FCF2D5

To center it, we add justify-content:center; 12EC74A5 E3B9 47B9 BC00 77E4565DDDB1

Add grid-gap:20px; ->

C7790B36 A3EB 4AD8 902C 5B0ADD9FAF8F

If you know the amount of columns you will have but you do not know the size of the content within them, this is a good use case.

Example 8 - Unknown Number of Items

In this example you want the items to take up as much room as you want but you don’t know how many columns there will be. Once you hit the min max value, they will start to wrap.

Goal ->

Starting ->

 <!— Unknown Amount of Elements >
    <script>
      function addItem() {
        const unknown = document.querySelector(.unknown”);
        unknown.innerHTML += `<div class=“item”>${
          unknown.childElementCount
        }</div>`;
      }
    </script>
    <button onClick=“addItem()”>+ Add</button>
    <div class=“unknown”>
      <div class=“item”>1</div>
      <div class=“item”>2</div>
      <div class=“item”>3</div>
    </div>

    <style>
      .unknown {
      }
    </style>

263D6A23 3D2C 4D1C BFAD DBF0DFB0E11C

add ->

      .unknown {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(50px, 1fr));
        grid-gap: 20px;
      }

Gives you -> 62F75653 4C80 4571 9180 84D71F4DEF6C

And now they will wrap after hitting the minmax.

Example 9 - Variable Widths Each Row

Goal -> CC2AC8BC 2FBF 4CC6 B8AD AC45A68CA154

Starting ->

  <div class=“flex-container”>
    <div class=“item”>Short</div>
    <div class=“item”>Longerrrrrrrrrrrrrr</div>
    <div class=“item”>💩</div>
    <div class=“item”>This is Many Words</div>
    <div class=“item”>Lorem, ipsum.</div>
    <div class=“item”>10</div>
    <div class=“item”>Snickers</div>
    <div class=“item”>Wes Is Cool</div>
    <div class=“item”>Short</div>
  </div>
  <style>
    .flex-container {}

    .flex-container>* {
      margin: 10px;
    }
  </style>

DFE34B84 FFF4 4D0C A09A 039875C24B66

You wouldn’t use grid for this one.

Add display:flex to the .flex-container. ->

EED614F4 A71F 4ECE 9D91 E4F9D7C9B7A1

Add flex-wrap:wrap ->

4B73037E EF06 4DA4 9866 3AB44713494E

We can go to each flex-item and put value of 1 and it will fit it in as perfectly as we want.

.flex-container > * {
  margin: 10px;
  flex: 1;
}

0793D945 34E4 4285 BACB 065FD20A8277


22 - Recreating CodePen

Goal ->

7FF97180 EE15 4B90 AED1 A494DC09C418

Wes has started us off with some HTML. It contains 4 main parts inside of a “codepen” div ->

A26A2BC4 F641 4F45 A617 08C0F2098845

Inside of that we have our pen, code, preview and settings, and inside each of those there are smaller subset grids.

We want the header to take up as much room as it needs, and also for the footer to take up as much room as it needs. The other two we want to divide evenly.

.codepen {
  display: grid;
  grid-template-rows: auto 1fr 1fr auto;
}

63A0F555 A18A 4675 B891 D0B506822F82

However, should the footer (console, assets) be at the bottom? The issue is the codepen doesn’t have a height on it and you need an explicit height in order for it to work.

Add height:100vh

Next we are going to work on the editor. There is one section with class of .code and within it 3 divs with class of .editor

We will make code element display grid and then have 3 columns that repeat equally ->

.code {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}

67E4216C 610A 4C81 A9E8 0096D3EB158B

Next we will work on the header.

7D9F170A D955 4CD7 96FA 80D36A0F963B

What we want to do here is have the pen details take up as much room as it can, minus the size of the buttons and the avatar.

Add

.pen {
  display: grid;
  grid-template-columns: 1fr;
  grid-auto-flow: column;
}

They are being stretched which we can fix using align-items:center; CC8E1E20 7162 4605 B2EC C1D9065BD4C4

For the bottom one div (.preview) we just need to add display:grid; .

C9604E77 5B10 481B 9447 BF0A70BCACE3

Now we will add some styling. First to the header and buttons ->

.pen {
  …background: black;
  border-bottom: 5px solid var(--grey);
  color: white;
  padding: 10px;
}
/* Buttons */
.button {
  background: var(--grey);
  border: 0;
  color: white;
  padding: 10px;
  border-radius: 5px;
  font-size: 15px;
}

.button-small {
  font-size: 12px;
  padding: 4px;
}

F5D60E4E 3C56 4E1C A980 B60E0D2A7A3F

We want to add this style to the button -> CA0D69F4 3B67 4192 BDDA 1B1DDBEAE6A8

In order to do that, we are going to use the ::before element on the button with class .button-dirty

We need to do the typical song-and-dance associated with using ::before

.button—dirty::before {
  background: #ffc600;
  display: block;
  content: “”;
  height: 2px;

That gives us ->

225156E0 92C4 40DC BB8A F1D064E7ECBF

However we are going to position it absolutely. We need to make .button {… position:relative;} and then add the following ->

.button—dirty{width: calc(100% - 6px);
  position: absolute;
  left:3px;
top:3px;

08E4564D 0D10 407D AA9A 2429608A09FD

Next we will work on the editors. Each editor in itself, has a header, which needs to be side by side. All the elements are on the left except the dropdown which is to the right.

We want it to look like this ->

72EB514C 9E14 4DE8 B7E9 5D80FF68C15F

.editor__header {
  display: grid;
  grid-template-columns: auto 1fr auto;
}

Which gives you -> 06E65588 F7C4 4E58 B0FC FA8BFC633583

However they are stretching. We want to add align-items:center; and add padding on the header.

1E679358 9A51 4070 9E5F 889E4AB585BE

We add some more styling ->

.code {
  ... background: #1b2b34;
}
.editor__header {
  ... padding: 5px;
  grid-gap: 5px;
  background: rgba(0, 0, 0, 0.1);
}

0BC11C0A 9F15 4065 AE51 BF8EF3E74A6B

We want the code editor to take up the entire space.

So we need to make the editor itself display:grid.

D81C42FF AA16 4305 929D CBFC670295BF

.editor {
  display: grid;
}

We also need to make the .editor__code display grid because it has two children that need to go below each other. We want the gutter to be small and the code portion to take up the rest the space

.editor__code {
  display: grid;
  grid-template-columns: auto 1fr;
}

A87DFF48 95B3 4FC0 8297 A2482891C952

27240906 986B 4441 86AB 2158333F91A7

We want the numbers in the gutter to go on each of their own lines.

.editor__number {
  display: block;
  padding: 0 10px;
}

FD2D0D50 9A89 4142 B6F9 778AB569F4F1

Add some styling to the editor ->

.editor__input {
  resize: none;
  background: none;
  border: 0;
  color: grey;
  font-size: 16px;
  line-height: 19px;
}

16F1565E AF16 4A46 8087 F57700A04F8D

Finally we need to style the footer.

.settings {
  padding: 5px;
  background: black;
  border-top: 1px solid grey;
}

B689C499 1098 4863 B92B E42678A0703E


23 - Bootstrappy Grid with CSS Variables

We are going to create a more rigid grid in this exercise similar to bootstrap grid.

Starting point ->

 <div class=“grid”>
    <div class=“item”>1</div>
    <div class=“item”>2</div>
    <div class=“item”>3</div>
    <div class=“item”>4</div>
  </div>

  <style>
    .grid {}
  </style>

4EE85D70 AFD6 4DA1 9B74 AA72549DA797

Add

.grid {
  display: grid;
  grid-gap: 20px;
  grid-template-columns: repeat(12, 1fr);
}

085627A0 9C16 4D46 8A5D CC4BEABEE3E2

One issue here is if one of the items has more content, such as below, they are no longer even sizes.

FD21B4B9 9CB1 46A3 94BE 7AC8D853B892

If you try to use % or calc, it still doesn’t work ->

2AA8C02B 1189 4733 8758 D0FDED80D517

One fix for that is go into the item and give it a min-width of 0 and deal with overflowing text accordingly.

.item{min-width: 0;}

F7A542FE 0F4C 42EE BE35 69D14601C546

Another way to do this is to modify

.grid {
  ... grid-template-columns: repeat(12, minmax(0, 1fr));
}

.item {
  width: 100%;
}

4F6870C2 F741 4DD1 85D8 BAE9075B41ED

Next we are going to work on spanning the different items.

We can do this using css variables.

.item {
  min-width: 0;
  width: 100%;
  --span: 1;
  grid-column: span var(--span);
}

And in the html overwrite that variable like so ->

<div class=“item” style=“—span:3;”>2</div>

1870ABB8 E089 45AA BE99 AD6736FB1EF4

You could also do something similar with cols. Instead of setting the number of columns in the css explicitly, we could do something like this ->

grid-template-columns: repeat(var(—cols, 12), minmax(0, 1fr));

Where 12 is the fallback if no variable is provided and then in the html modify like so ->

<div class=“grid” style=“—cols:10;”>

Next we will make the second item span 7 so all the spaces are taken up and then we will make another nested grid inside of it.

<div class="item" style="--span:7;">
  <div class="grid" style="--cols:2;">
    <div class="items">1</div>
    <div class="items">2</div>
  </div>
</div>

0DF6EA69 4339 4E7D AACE 40F708CEF461

You can use negative margins if you need to deal with the grid gap.


24 - Responsive Website Example

Goal ->

Starting Code ->

  <div class=“wrapper”>
    <div class=“top”>
      <header class=“hero”>
        <h1>Terry’s Taco Joint</h1>
        <p>Pretty Good Tacos!</p>
      </header>
      <div class=“cta cta1”>
        <p class=“price”>$1.99</p>
        <p>Tacos</p>
      </div>
      <div class=“cta cta2”>
        <p class=“price”>$3.99</p>
        <p>Kombucha</p>
      </div>

    </div>
    <nav class=“menu”>
      <button aria-expanded=“false” aria-controls=“menu-list”>
        <span class=“open”></span>
        <span class=“close”>×</span>
        Menu
      </button>
      <ul id=“menu-list”>
        <li>
          <a href=“”>Tacos</a>
        </li>
			...
      </ul>
    </nav>

    <section class=“features”>
      <div class=“feature”>
        <span class=“icon”>🌮</span>
        <h3>Tacos</h3>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Animi, assumenda.</p>
      </div>
     ...
    </section>

    <section class=“about”>
      <img src=“images/queso-taco.png” alt=“Yummy Taco” class=“about__mockup”>
      <div class=“about__details”>
        <h2>Featured Taco</h2>
        <p>Slim Profile, easy to hold and loaded with cheese.</p>
        <p>This is the one you have been waiting for</p>
        <button>Learn More →</button>
      </div>
    </section>


    <section class=“gallery”>
      <h2>Instant Grams</h2>
      <img src=“https://source.unsplash.com/random/201x201” alt=“”>
      ...
    </section>
  </div>
body {
  font-size: 15px;
}

button {
  background: #ffc600;
  border: 0;
  padding: 10px 20px;
}

img {
  max-width: 100%;
}

4924B63A E701 4A38 A1E1 ACE4E9F02125

We will start with the top section and if we display grid on the top.

.top{
display:grid;}
}

Instead of defining the columns, we are going to define grid template areas.

6ACE7D7F 48E5 4E22 B902 3FD19F150FE1

Add

grid-template-areas:
  "hero hero cta1"
  "hero hero cta2";

715927FB 7FAB 4508 9E60 A018F666962B

It doesn’t look great here because we need to go ahead and select them.

.hero {
  grid-area: hero;
}

-> 3791B111 7346 4053 A195 D39D029754AE

Cta1 and Cta2 automatically fall into place but we are going to place them anyway

.cta1 {
  grid-area: cta1;
}
.cta2 {
  grid-area: cta2;
}

Next we are going to style the hero like so ->

.hero {
  grid-area: hero;
  min-height: 400px;
  background: white url(images/taco.jpg);
  background-size: cover;
  background-position: bottom right;
  padding: 50px;
}

B313C7AB 422A 42CE 8B2D C9E00AC68E51

For the text, we want it like so ->

B6268189 1F26 48C9 A1CB A7096C6D2B97

With grid, we make the hero a grid container, and the h1 and paragraph are the grid items.

.hero {display: grid;
  justify-content: start;
  align-content: center;

Which gives you this ->

7C14F748 48C6 4897 916A 2D3C6A498F01

However the issue is because it’s column based, the columns are going to be as wide as the widest one. That is how grid works. So instead of grid, we are going to use flex box.

  display: flex;
  flex-direction: column;
  align-items: start;
  justify-content: center;
}

25B0092C 2E93 41DE BC3F 7ACE4DEC1B32

When you want variable width is a good example of when you’d turn to flex box over grid.

Next we will do out CTAs. First add grid-gap:20px to .top Give CTAs background color:

.cta {
  background: var(—yellow);
}

E6DA1725 3509 4DD8 8661 12BCEFCEB6A3

We want to center the text on the CTAs

.cta {
  background: var(—yellow);
  display: grid;
  align-items: center;
  justify-items:center;

However now the grid items are stretching 8B263649 C8FB 4BAA 9F07 41B27A32E8CF

We want the text to be together ->

20015D25 A94D 48B1 B7F5 9A854A4AB804

If you add align-content:center it will bring the text together and then if you add .cta p { margin:0;} it will give you this ->

BABB4F24 FF03 4844 88DB BB88FCDB79DC

Next we add some styling for the price

.price {
  font-size: 60px;
  font-weight: 300;
}

Moving onto navigation..

We want each of the menu items to take up as much space as they can, which is a good use case for our minmax values.

.menu ul {
  padding: 0;
  margin: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
}

99A5EFFF 328D 4BAA 9349 585DA6A925A9

Instead of styling the li we are going to style the links.

.menu a {
  background: var(--yellow);
}

However that gives us -> CFA869EC B01E 454C 88E0 0FF621C78CC5 And that is because link tags are inline by default so we need to add display:block ->

34FD7A84 A618 4B13 BE67 A709B4EE8AC2

Add some more styling

.menu a {
  background: var(--yellow);
  display: block;
  text-decoration: none;
  padding: 10px;
  text-align: center;
  color: var(--black);
  text-transform: uppercase;
  font-size: 20px;
}

Add grid-gap:20px; margin: 20px 0; to .menu ul ->

39EC8D7C D0EB 40A3 AD6D 13A7B5BBC896

Right now you can still see the menu, which should only be visible on mobile. We are using aria-controls to hide / expand the menu instead of a bunch of classes -> 6214E031 9BC2 4DF4 B618 BC5D05CA9B25

F9E74FB6 033B 454B B3FF 9DC2BAF39B0A

We are use an attribute selector to display:none on the menu.

[aria-controls="“menu-list”"] {
  display: none;
}

Now we are going to move into the features section.

.features {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

20E4277D FEBF 49F8 A961 1F8DB56AC205

Next we are going to style each feature to see if it’s responsive.

.features {
  ... grid-gap: 20px;
}

.feature {
  background: white;
  padding: 10px;
  border: 1px solid white;
  text-align: center;
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.1);
}

.feature .icon {
  font-size: 50px;
}

.feature p {
  color: rgba(0, 0, 0, 0.5);
}

Next we are moving onto the about section where we are displaying the taco.

We want the image to be 400px wide and the text take up the remaining space.

.about {
  background: white;
  padding: 50px;
  display: grid;
  grid-template-columns: 400px 1fr;
}

1F3EBD63 30B4 4A4D A130 EC90A3C25FF2

We want to vertically center everything. Add align-items:center;

C512D3CB 11D0 417C AC27 1F7F5E976DE2

Instead of adding margin on everything, we are going to take our wrapper and make it display grid, not put any columns in it and give it a grid gap to all the grid items. This will also allow use the order property to rearrange things on mobile.

Now we are working on gallery.

We are going to make it a grid and we want all the items to display 200px minimum and 1fr maximum.

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

All the images are slightly different sizes so we need to account for that. Add grid-gap:20px and .gallery img { width:100%} 2A2D07D2 3DCB 4805 BAD9 51062AEC5FFC

We want the h2 to span all the way across however it’s a grid item. What we will do is make it span all the way across ->

.gallery h2 {
  grid-column: 1 / -1;
}

4FC4E5ED 9F07 4940 A449 AFCBD4957B51

However we want this type of effect -> 0D2E26F9 7DF5 4C05 8445 EDDA4A125A33

We are going to make the h2 display:grid and use a before and after attribute which are considered grid items along with the content inside of the h2.

.gallery h2 {
  grid-column: 1 / -1;
  display: grid;
}

.gallery h2::before,
.gallery h2::after {
  display: block;
  content: "";
  height: 10px;
  background: #ffc600;
}

C7DA3205 09B7 40C9 A2A6 E3EB4EE67A16

We want the text to be in the middle and have the before and after split whatever is left over. Add to the h2 grid-template-columns: 1fr auto 1fr;

CAA60D6A 01BC 499C A9B6 AD5CD7349B88

Add to the h2

align-items: center;
grid-gap: 20px;

DFA833BD 204D 4A01 865D F82F634D22D8

However we want these to be gradients.

7A3DAC59 C2E2 4A44 AC0E 3E4D2083D0A4

.gallery h2::before,
.gallery h2::after {
  display: block;
  content: “”;
  height: 10px;
  background: linear-gradient(
    to var(—direction, left),
    var(—yellow),
    transparent
  );
}

.gallery h2::after {
  —direction: right;
}

Now we will start on the responsive portion.

As we get smaller, we want to put the CTA underneath the banner image and make the banner image span across.

@media (max-width: 700px) {
  .top {
    grid-template-areas:
      “hero hero”
      “cta1 cta2”;
  }
}

2003332D 1AF5 494F ACA4 25B648C84A51

Under 500px we want to make them go one after the other like so ->

@media (max-width: 500px) {
  .top {
    grid-template-areas:
      “hero”
      “cta1”
      “cta2”;
  }
}

39371513 047F 40EB A560 8BB61EC3DBCD

Next is the menu. When we hit 1000pixels, we want to flip the menu to the top.

@media (max-width: 1000px) {
  .menu {
    order: -1;
  }
}

Because menu is a direct descendent of our wrapper, by putting order: -1 it will put it above the actual top.

6BC952F7 1332 40D2 B655 9F5B4D0377D2

We want to re-show the menu button

[aria-controls="“menu-list”"] {
  display: block;
  margin-bottom: 10px;
}

Next we add ->

 .menu ul {
    max-height: 0px;
    transform: rotateX(90deg);
    transition: all 0.5s;
  }

Which hides the menu items by rotating them up. When we click the buttons it will hide and show the items.

When the button is clicked, we need the aria-expanded to be set to true or false.

We are going to do that with javascript.

    <script>
      const navButton = document.querySelector(“button[aria-expanded]);

      function toggleNav() {
        console.log(TOGGLE!);
      }

      navButton.addEventListener(“click”, toggleNav);
    </script>

Now we are going to destructure the target.

function toggleNav({ target }) {
  console.log(target)
}

The target is the button itself, the thing that was clicked.

DE759F30 F021 4865 81C1 0B1466F922D6

Now we want to get the aria expanded attribute.

function toggleNav({ target }) {
        const expanded = target.getAttribute("aria-expanded");
      }

The attribute returns a string true or false, not a boolean.

 const expanded = target.getAttribute(“aria-expanded”) === true || false;

Now we want to set the attribute of aria expended to be the opposite of the expanded value.

   navButton.setAttribute(“aria - expanded”, !expanded);

That is all the js we need

Now we go back to the 1000px media query and say when aria expanded=true, the unordered list that comes after it we are going to display grid on it.

  [aria-expanded=“true”] ~ ul {
    display: grid;
    max-height: 500px;
    transform: rotateX(0);
  }

What you can do is select the parent of the unordered list .menu and give it perspective:800px; and add to .menu ul { overflow:hidden}

The reason we added .menu ul{ max-height:0} and [aria-expanded=“true”] ~ ul { max-height: 500px }

Without it, it won’t slide up the menu, you’ll see something like this ->

Next is the x value on the menu 3F21A30A 18AC 4ACD BD3D 0B5CC3C7EAC0

We want to hide and show them. 230C5C7C 8C17 4AFB 9DA7 7D88BBA550E4

In the max 1000px media query, add the following

[aria-expanded="“false”"] .close {
  display: none;
}
[aria-expanded="“true”"] .close {
  display: inline-block;
}
[aria-expanded="“true”"] .open {
  display: none;
}

This will hide the x when it is closed, and show the x when the menu is open.

Next is our taco. We will add the code for our 700px media query and make the taco one column instead of the two.

@media (max-width: 700px) {/*About*/
  .about {
    grid-template-columns: 1fr;
  }
}

7E3F0D4A 1515 484B 92DC 0972C4A76B05


25 - Full Bleed Blog Layout

We will be building a blog layout. CSS grid is good for position text as well as creating a full application layout.

Starting Point:

 <article class="post">
    <h2>Chapter Three: The Great American Game</h2>

    <p>Dear Diary,</p>

    <p>Grandfather's creaky as his front porch, loads his shotgun beneath the awning, spittoon restless for rain, carpenter's
      chair against the whistling air. Rocking, back and forth, rocking snap shot picture - worth it, just like the movies</p>

    <div class="tip tip-right">
      <p>This is a song by
        <a href="http://levithepoet.net/">Levi The Poet</a>
      </p>
    </div>


    <p>She said that he loved baseball, and James Earl Jones; said that he's got god talking inside of his thoughts while he's
      rounding those bases on his way back home</p>

    <blockquote>
      <p>"If you build it, they will come"</p>
    </blockquote>

    <p>If you build it, they will come (and baby listens to what the Lord say). But I've been getting pretty worn, building
      for nearly a decade</p>

    <figure>
      <img src="https://source.unsplash.com/1000x300" alt="Big Ass Image">
      <figcaption>Super Nice Photo</figcaption>
    </figure>
 <style>
    :root {
      --yellow: #ffc600;
    }

    html {
      color: #444;
      font-family: Cambria, Cochin, Georgia, 'Times New Roman', Times, serif;
      font-size: 20px;
    }

    p {
      line-height: 1.8;
    }

    img {
      max-width: 100%;
    }

    a {
      color: black;
      text-decoration: underline wavy var(--yellow);
    }

    h1,
    h2 {
      font-size: 80px;
      font-style: italic;
      font-weight: 100;
      margin: 0;
    }
  </style>

A0709887 20F2 4150 B923 F1D1EACB5AAB

What we are going to do is take the post and make it a three column grid. Most of the content will take up the centre column, images will sometimes span all three across.

We will take the .post and make it display:grid, and put max-width: 1000px and margin:200px auto;.

To make the grid, we are going to make three columns. Initially Wes though to do it with grid-template-columns:15% 60% 25%; grid-gap:20px , however the issue there is grid-gap will give you horizontal scroll because it is added on top of the grid column sizes, not taken away from it.

Since all the percentages are base 5, we can turn them into frs.

grid-template-column: 3fr 12fr 5fr Now everything will add up regardless of how much grid-gap is being added.

Modify the grid-gap to be 10px 50px so the column gaps are 50px but the row gaps are 10px.

324F5DCC 31D5 4254 8F3F 78B4D499592A

Now we have a problem where every single paragraph/element is taking up a spot. What we need to do is select all of the elements and put them in the centre column.

We want to select every single direct child of the .post element. We are going to start at 2, and span 1.

.post > * {
  grid-column: 2 / span 1;
}

We can also write it like grid-column: 2 / -2 which is more resilient because if more columns are added, it will still span up till two from the end. We want the gutters empty, and all the content in the middle.

9D1C9A86 54D5 46BF 8F82 BA46780846F0

Next we are going to start working with the figures. We want them to span all the way across.

Add ->

.post > figure {
  margin: 0;
  grid-column: 1 / -1;
}
figcaption {
  font-size: 10px;
}

4A6B8F28 5316 4FA3 86E0 34C03F545BAB

Next we are going to work on the block quotes that we have. We want them to span all the way across.

8E070284 40D6 4AA8 9F0A C163375FFE9F

.post > blockquote {
  grid-column: 1 / -1;
  font-style: italic;
  font-size: 60px;
  text-align: center;
  margin: 0;
}

Next we have the tips which we want to go to the left or the right. What they should do, is go into the actual gutters.

.tip {
  background: #fafafa;
  padding: 10px;
}
.tip-left {
  grid-column: 1 / span 1;
  text-align: right;
  border-right: 2px solid var(--yellow);
}

932B01FD AF27 429D BA75 7CE41D3562D0

For the left tips, we want to start at one and only span one space. The rest of the content will fill up that space because we have told all the children to go into the center column.

Next we do the right tip. We want it to span 1, and end at the last one.

.tip-right {
  grid-column: span 1 / -1;
  border-left: 2px solid var(—yellow);
}

7E524D21 FA3D 477F A90F D1D5AE138AB6

One thing is if there is a lot of content in the right/left tip for example, it will force the other columns to have a lot of empty space, which is just how grid works. 11578783 BC48 47E5 B554 7C1B49731EFA

One thing you could do is, if you know you don’t have a bunch of tips one after the other, you could also make the tips span a couple of rows each.

.tip {
  background: #fafafa;
  padding: 10px;
  grid-row: span 3;
}

3BE5441F 5B31 4CAF 8651 3BA7123422C4

One issue is if a tip doesn’t have a lot of content it will span unnecessarily like so ->

D3415B6E 81E8 49AD A2E2 6316951CE3C5

To fix that, you could add align-self:start and it will only go as high as it needs to instead of stretching high ->

4FB4D0BB 4582 467C A445 926921EA5B91