1

I created a layout with grid-css that contains 12 columns in the center with a maximum-width and 2 columns which will only be shown on large screens. This technique is based on the following article. (In the example the max-width is set to a small number, to make it easier to examine)

The problem I want to solve is:
I want to use classes to determine how many columns wide an element should be. Like you can see in the example below, I have a class col-10 and col-6. Similar to the bootstrap framework.

Is there some way I can say that the element with a class "col" for example, should be always inside the main column and ignore the outer columns which are included in the full column?

At the moment the only solution I found was giving the first element in a row, the correct starting point. (In the example it is the class "main-start")

Example code:

*{
  margin: 0;
  padding: 0;
  font-family: sans-serif;
}

nav{
  display:flex;
  justify-content: flex-end;
}

a{
  text-decoration:none;
  color:white;
  font-size: 10px;
  background-color: orange;
  padding: 0.5em;
}

.grid{
    display: grid;
    grid-template-columns:
        [full-start]minmax(0, 1fr)
        [main-start] repeat(12, minmax(0, 40px)) [main-end]
        minmax(0, 1fr)
        [full-end];
}

.main-start{
  grid-column-start: main-start;
}

.col-6{
  grid-column-end: span 6;
}

.col-10{
  grid-column-end: span 10;
}

.full-width{
  grid-column:full;
}

.gradient{
  color: white;
  text-align:center;
  height: 90px;
  background:linear-gradient(to bottom right, red,coral);
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=">
  <title>Grid centered design with full width elements</title>
</head>
<body>
  <header class="grid">
    <h1 class="col-6 main-start">MyWebsiteTitle</h1>
    <nav class="col-6">
      <a href="#">Page1</a>
      <a href="#">Page2</a>
      <a href="#">Page3</a>
    </nav>
    <p class="col-10">This is not inside main because it has no main-start class</p>
    <div class="full-width gradient">A full-width banner</div>
  </header>
</body>
</html>
Luhn
  • 706
  • 6
  • 15

2 Answers2

1

An idea is to consider an empty element that will fill the first column which will force all the element to start where you want:

* {
  margin: 0;
}

nav {
  display: flex;
  justify-content: flex-end;
}

.grid {
  display: grid;
  grid-template-columns: 
    [full-start]minmax(0, 1fr) 
    [main-start] repeat(12, minmax(0, 40px)) [main-end] minmax(0, 1fr) [full-end];
}
/* added */
.grid::before {
  content:"";
  grid-column:full-start/main-start;
  grid-row:span 100; /* take a lot of rows */
}
/**/

.col-6 {
  grid-column-end: span 6;
}

.col-10 {
  grid-column-end: span 10;
}

.full-width {
  grid-column: full;
}

.gradient {
  color: white;
  text-align: center;
  height: 90px;
  background: linear-gradient(to bottom right, red, coral);
}
<header class="grid">
  <h1 class="col-6">MyWebsiteTitle</h1>
  <nav class="col-6">
    <a href="#">Page1</a>
    <a href="#">Page2</a>
    <a href="#">Page3</a>
  </nav>
  <p class="col-10">This is not inside main because it has no main-start class</p>
  <div class="full-width gradient">A full-width banner</div>
</header>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • Thanks for this solution! looks great! I didn't think of the option where you overlap your full-width column with the invisible column. – Luhn Aug 18 '20 at 11:25
  • Is it possible that it does not combine well with the gap property? – Luhn Aug 18 '20 at 11:31
  • 1
    @Luhn yes, it won't work well if you have row gap, you need to consider margin instead of gap to use this trick or instead of 100 use the exact number of row you have – Temani Afif Aug 18 '20 at 11:35
0

As a response to the problem with the row-gap with the previous answer. Here is an example where the row-gap is replaced with a margin:

*{
  margin: 0;
  padding: 0;
  font-family: sans-serif;
}

nav{
  display:flex;
  justify-content: flex-end;
}

a{
  text-decoration:none;
  color:white;
  font-size: 10px;
  background-color: orange;
  padding: 0.5em;
}

.grid{
    display: grid;
    /* added */
    column-gap: 0.5rem;
    /**/
    grid-template-columns:
        [full-start]minmax(0, 1fr)
        [main-start] repeat(12, minmax(0, 40px)) [main-end]
        minmax(0, 1fr)
        [full-end];
}

/* added */
.grid::before {
  content:"";
  grid-column:full-start/main-start;
  grid-row:span 100; /* take a lot of rows */
}

.grid > *:not(:last-child) {
    /* row-gap */
    margin-bottom: 0.5rem;
}
/**/

.main-start{
  grid-column-start: main-start;
}

.col-6{
  grid-column-end: span 6;
}

.col-10{
  grid-column-end: span 10;
}

.full-width{
  grid-column:full;
}

.gradient{
  color: white;
  text-align:center;
  height: 90px;
  background:linear-gradient(to bottom right, red,coral);
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=">
  <title>Grid centered design with full width elements</title>
</head>
<body>
  <header class="grid">
    <h1 class="col-6 main-start">MyWebsiteTitle</h1>
    <nav class="col-6">
      <a href="#">Page1</a>
      <a href="#">Page2</a>
      <a href="#">Page3</a>
    </nav>
    <p class="col-10">This is not inside main because it has no main-start class</p>
    <div class="full-width gradient">A full-width banner</div>
  </header>
</body>
</html>
Luhn
  • 706
  • 6
  • 15