3

I'm trying to position pseudo-elements, as should be possible according to the specification, on a grid. This works great for my outer layout which I have set on the <body>, but it doesn't work for the <header> which itself is a grid.

How can I position the header nav:after element in the right column of the grid? Why doesn't it work in my example?

I appreciate any help! Here is the code:

body {
  display: grid;
  grid-template-columns: 1fr 800px 1fr;
}
header {
  grid-column: 1 / 4;
  grid-row: 1;

  display: grid;
  grid-template-columns: 1fr 800px 1fr;
}

/* Works great */
header:before {
  content: 'Left';
  grid-column: 1 / 2;
}

/* Doesn't work, treated as a child element */
header nav:after {
  content: 'Right';
  grid-column: 3 / 4;
}
header nav {
  grid-column: 2 / 3;
}
<body>
  <header>
    <nav>
    <ul>
      <li><a href='#'>Link</a></li>
      <li><a href='#'>Link</a></li>
      <li><a href='#'>Link</a></li>
    </ul>
    </nav>
  </header>
</body>    

Thank you!

kukkuz
  • 41,512
  • 6
  • 59
  • 95
Sebastian
  • 517
  • 1
  • 5
  • 12

2 Answers2

3

nav:after is a child element of nav. So make your nav a grid too - its not at the moment.

Or you can use header:after instead of nav:after- see demo below:

body {
  display: grid;
  grid-template-columns: 1fr 800px 1fr;
}

header {
  grid-column: 1 / 4;
  grid-row: 1;
  display: grid;
  grid-template-columns: 1fr 800px 1fr;
}


/* Works great */

header:before {
  content: 'Left';
  grid-column: 1 / 2;
}


/* CHANGED THIS*/

header:after {
  content: 'Right';
  grid-column: 3 / 4;
}

header nav {
  grid-column: 2 / 3;
}
<header>
  <nav>
    <ul>
      <li><a href='#'>Link</a></li>
      <li><a href='#'>Link</a></li>
      <li><a href='#'>Link</a></li>
    </ul>
  </nav>
</header>
kukkuz
  • 41,512
  • 6
  • 59
  • 95
  • Hello kukkuz, thank you for your answer! From what I can see in my header example, the header:before element is actually a child of the body, otherwise I would not be able to position it on the left, would I? I am trying to achieve the same, I would need the ul element to have a :before or :after pseudo element, but need it to position it on the right. However, I cannot see how this situation is any different? Why does it not work the same way? – Sebastian Sep 05 '17 at 11:05
  • 1
    `header: before` is a child of `header`... `:after` and `:before` psuedo elements are child of the element to which you apply it to... – kukkuz Sep 05 '17 at 11:07
  • Please correct me if I am wrong, but I think it is not. Look at the following simplified example. If I can position :before on the body's grid, header:before must now be a child of body, a sibling of header. I think this is what the following specification says as well: https://developer.mozilla.org/en-US/Firefox/Releases/23#CSS `body { display: grid; grid-template-columns: 1fr 800px 1fr; } header { grid-column: 1 / 4; grid-row: 1; } header:before { content: 'Left'; grid-column: 1 / 2; }` `
    `
    – Sebastian Sep 05 '17 at 11:13
  • My question is, why does it work the same way for nav? – Sebastian Sep 05 '17 at 11:14
  • 2
    @Sebastian, unfortunately, your guess is wrong. You can prove that if you try to place `header` and `header:before` into different rows of the `body`'s grid. Your example _looks like_ `header` and `header:before` both share the same `body`'s grid area because `header:before` is part of the _content_ of the `header`. You can see it with the Grid Inspector tool in Firefox Devtools. The doc you linked is not a spec, it's a Release Note for old Firefox version, and it says nothing abt grid. In fact, `:before` [is the child of the element](https://developer.mozilla.org/en-US/docs/Web/CSS/::before). – Ilya Streltsyn Sep 05 '17 at 11:38
1

Pseudo elements in a grid container are considered children of the container. References:

Therefore, unless a pseudo-element is absolutely positioned, it is a grid item. Reference:

Here's a demonstration based on your code:

body {
  display: grid;
  grid-template-columns: 1fr 300px 1fr;
  text-align: center;
  border: 1px solid black;
}

body::before {
  content: "pseudo - \a left sibling \a of header";
  white-space: pre;
  grid-column: 1 / 2;
  background-color: salmon;
}

body::after {
  content: "pseudo - \a right sibling \a of header";
  white-space: pre;
  grid-column: 3 / 4;
  background-color: lightgreen;
}

header {
  grid-column: 2 / 3;
  background-color: yellow;
  padding: 5px;
  display: grid;
  grid-template-columns: 1fr 100px 1fr;
  grid-gap: 5px;
}

header nav {
  grid-column: 2 / 3;
  border: 1px dashed red;
}

header::before {
  content: "pseudo - \a left sibling \a of nav";
  white-space: pre;
  grid-column: 1 / 2;
  border: 1px dashed red;
}

header::after {
  content: "pseudo - \a right sibling \a of nav";
  white-space: pre;
  grid-column: 3 / 4;
  border: 1px dashed red;
}
<body>
  <header>
    <nav>
      <ul>
        <li><a href='#'>Link</a></li>
        <li><a href='#'>Link</a></li>
        <li><a href='#'>Link</a></li>
      </ul>
    </nav>
  </header>
</body>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701