htmlcsscenteringcss-grid

Centering in CSS Grid


I'm trying to create a simple page with CSS Grid.

What I'm failing to do is center the text from the HTML to the respective grid cells.

I've tried placing content in separate divs both inside and outside of the left_bg and right_bg selectors and playing with some of the CSS properties to no avail.

How do I do this?

html,
body {
  margin: 0;
  padding: 0;
}

.container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 100vh;
  grid-gap: 0px 0px;
}

.left_bg {
  display: subgrid;
  background-color: #3498db;
  grid-column: 1 / 1;
  grid-row: 1 / 1;
  z-index: 0;
}

.right_bg {
  display: subgrid;
  background-color: #ecf0f1;
  grid-column: 2 / 2;
  grid_row: 1 / 1;
  z-index: 0;
}

.left_text {
  grid-column: 1 / 1;
  grid-row: 1 / 1;
  position: relative;
  z-index: 1;
  justify-self: center;
  font-family: Raleway;
  font-size: large;
}

.right_text {
  grid-column: 2 / 2;
  grid_row: 1 / 1;
  position: relative;
  z-index: 1;
  justify-self: center;
  font-family: Raleway;
  font-size: large;
}
<div class="container">
  <!--everything on the page-->

  <div class="left_bg">
    <!--left background color of the page-->
  </div>
</div>

<div class="right_bg">
  <!--right background color of the page-->
</div>

<div class="left_text">
  <!--left side text content-->
  <p>Review my stuff</p>

  <div class="right_text">
    <!--right side text content-->
    <p>Hire me!</p>
  </div>
</div>


Solution

  • This answer has two main sections:

    1. Understanding how alignment works in CSS Grid.
    2. Six methods for centering in CSS Grid.

    If you're only interested in the solutions, skip the first section.


    The Structure and Scope of Grid layout

    To fully understand how centering works in a grid container, it's important to first understand the structure and scope of grid layout.

    The HTML structure of a grid container has three levels:

    Each of these levels is independent from the others, in terms of applying grid properties.

    The scope of a grid container is limited to a parent-child relationship.

    This means that a grid container is always the parent and a grid item is always the child. Grid properties work only within this relationship.

    Descendants of a grid container beyond the children are not part of grid layout and will not accept grid properties. (At least not until the subgrid feature has been implemented, which will allow descendants of grid items to respect the lines of the primary container.)

    Here's an example of the structure and scope concepts described above.

    Imagine a tic-tac-toe-like grid.

    article {
      display: inline-grid;
      grid-template-rows: 100px 100px 100px;
      grid-template-columns: 100px 100px 100px;
      grid-gap: 3px;
    }
    

    enter image description here

    You want the X's and O's centered in each cell.

    So you apply the centering at the container level:

    article {
      display: inline-grid;
      grid-template-rows: 100px 100px 100px;
      grid-template-columns: 100px 100px 100px;
      grid-gap: 3px;
      justify-items: center;
    }
    

    But because of the structure and scope of grid layout, justify-items on the container centers the grid items, not the content (at least not directly).

    enter image description here

    article {
      display: inline-grid;
      grid-template-rows: 100px 100px 100px;
      grid-template-columns: 100px 100px 100px;
      grid-gap: 3px;
      justify-items: center;
    }
    
    section {
        border: 2px solid black;
        font-size: 3em;
    }
    <article>
        <section>X</section>
        <section>O</section>
        <section>X</section>
        <section>O</section>
        <section>X</section>
        <section>O</section>
        <section>X</section>
        <section>O</section>
        <section>X</section>
    </article>

    Same problem with align-items: The content may be centered as a by-product, but you've lost the layout design.

    article {
      display: inline-grid;
      grid-template-rows: 100px 100px 100px;
      grid-template-columns: 100px 100px 100px;
      grid-gap: 3px;
      justify-items: center;
      align-items: center;
    }
    

    enter image description here

    article {
      display: inline-grid;
      grid-template-rows: 100px 100px 100px;
      grid-template-columns: 100px 100px 100px;
      grid-gap: 3px;
      justify-items: center;
      align-items: center;
    }
    
    section {
        border: 2px solid black;
        font-size: 3em;
    }
    <article>
        <section>X</section>
        <section>O</section>
        <section>X</section>
        <section>O</section>
        <section>X</section>
        <section>O</section>
        <section>X</section>
        <section>O</section>
        <section>X</section>
    </article>

    To center the content you need to take a different approach. Referring again to the structure and scope of grid layout, you need to treat the grid item as the parent and the content as the child.

    article {
      display: inline-grid;
      grid-template-rows: 100px 100px 100px;
      grid-template-columns: 100px 100px 100px;
      grid-gap: 3px;
    }
    
    section {
      display: flex;
      justify-content: center;
      align-items: center;
      border: 2px solid black;
      font-size: 3em;
    }
    

    enter image description here

    article {
      display: inline-grid;
      grid-template-rows: 100px 100px 100px;
      grid-template-columns: 100px 100px 100px;
      grid-gap: 3px;
    }
    
    section {
      display: flex;
      justify-content: center;
      align-items: center;
      border: 2px solid black;
      font-size: 3em;
    }
    <article>
      <section>X</section>
      <section>O</section>
      <section>X</section>
      <section>O</section>
      <section>X</section>
      <section>O</section>
      <section>X</section>
      <section>O</section>
      <section>X</section>
    </article>

    jsFiddle demo


    Six Methods for Centering in CSS Grid

    There are multiple methods for centering grid items and their content.

    Here's a basic 2x2 grid:

    grid-container {
      display: grid;
      grid-template-columns: 1fr 1fr;
      grid-auto-rows: 75px;
      grid-gap: 10px;
    }
    
    
    /* can ignore styles below; decorative only */
    grid-container {
      background-color: lightyellow;
      border: 1px solid #bbb;
      padding: 10px;
    }
    grid-item {
      background-color: lightgreen;
      border: 1px solid #ccc;
    }
    <grid-container>
      <grid-item>this text should be centered</grid-item>
      <grid-item>this text should be centered</grid-item>
      <grid-item><img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt=""></grid-item>
      <grid-item><img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt=""></grid-item>
    </grid-container>

    Flexbox

    For a simple and easy way to center the content of grid items use flexbox.

    More specifically, make the grid item into a flex container.

    There is no conflict, spec violation or other problem with this method. It's clean and valid.

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

    grid-container {
      display: grid;
      grid-template-columns: 1fr 1fr;
      grid-auto-rows: 75px;
      grid-gap: 10px;
    }
    
    grid-item {
      display: flex;            /* new */
      align-items: center;      /* new */
      justify-content: center;  /* new */
    }
    
    /* can ignore styles below; decorative only */
    grid-container {
      background-color: lightyellow;
      border: 1px solid #bbb;
      padding: 10px;
    }
    grid-item {
      background-color: lightgreen;
      border: 1px solid #ccc;
    }
    <grid-container>
      <grid-item>this text should be centered</grid-item>
      <grid-item>this text should be centered</grid-item>
      <grid-item><img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt=""></grid-item>
      <grid-item><img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt=""></grid-item>
    </grid-container>

    See this post for a complete explanation:


    Grid Layout

    In the same way that a flex item can also be a flex container, a grid item can also be a grid container. This solution is similar to the flexbox solution above, except centering is done with grid, not flex, properties.

    grid-container {
      display: grid;
      grid-template-columns: 1fr 1fr;
      grid-auto-rows: 75px;
      grid-gap: 10px;
    }
    
    grid-item {
      display: grid;            /* new */
      align-items: center;      /* new */
      justify-items: center;    /* new */
    }
    
    /* can ignore styles below; decorative only */
    grid-container {
      background-color: lightyellow;
      border: 1px solid #bbb;
      padding: 10px;
    }
    grid-item {
      background-color: lightgreen;
      border: 1px solid #ccc;
    }
    <grid-container>
      <grid-item>this text should be centered</grid-item>
      <grid-item>this text should be centered</grid-item>
      <grid-item><img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt=""></grid-item>
      <grid-item><img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt=""></grid-item>
    </grid-container>


    auto margins

    Use margin: auto to vertically and horizontally center grid items.

    grid-item {
      margin: auto;
    }
    

    grid-container {
      display: grid;
      grid-template-columns: 1fr 1fr;
      grid-auto-rows: 75px;
      grid-gap: 10px;
    }
    
    grid-item {
      margin: auto;
    }
    
    /* can ignore styles below; decorative only */
    grid-container {
      background-color: lightyellow;
      border: 1px solid #bbb;
      padding: 10px;
    }
    grid-item {
      background-color: lightgreen;
      border: 1px solid #ccc;
    }
    <grid-container>
      <grid-item>this text should be centered</grid-item>
      <grid-item>this text should be centered</grid-item>
      <grid-item><img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt=""></grid-item>
      <grid-item><img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt=""></grid-item>
    </grid-container>

    To center the content of grid items you need to make the item into a grid (or flex) container, wrap anonymous items in their own elements (since they cannot be directly targeted by CSS), and apply the margins to the new elements.

    grid-item {
      display: flex;
    }
    
    span, img {
      margin: auto;
    }
    

    grid-container {
      display: grid;
      grid-template-columns: 1fr 1fr;
      grid-auto-rows: 75px;
      grid-gap: 10px;
    }
    
    grid-item {
      display: flex;
    }
    
    span, img {
      margin: auto;
    }
    
    /* can ignore styles below; decorative only */
    grid-container {
      background-color: lightyellow;
      border: 1px solid #bbb;
      padding: 10px;
    }
    grid-item {
      background-color: lightgreen;
      border: 1px solid #ccc;
    }
    <grid-container>
      <grid-item><span>this text should be centered</span></grid-item>
      <grid-item><span>this text should be centered</span></grid-item>
      <grid-item><img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt=""></grid-item>
      <grid-item><img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt=""></grid-item>
    </grid-container>


    Box Alignment Properties

    When considering using the following properties to align grid items, read the section on auto margins above.

    https://www.w3.org/TR/css-align-3/#property-index


    text-align: center

    To center content horizontally in a grid item, you can use the text-align property.

    grid-container {
      display: grid;
      grid-template-columns: 1fr 1fr;
      grid-auto-rows: 75px;
      grid-gap: 10px;
      text-align: center;  /* new */
    }
    
    
    /* can ignore styles below; decorative only */
    grid-container {
      background-color: lightyellow;
      border: 1px solid #bbb;
      padding: 10px;
    }
    grid-item {
      background-color: lightgreen;
      border: 1px solid #ccc;
    }
    <grid-container>
      <grid-item>this text should be centered</grid-item>
      <grid-item>this text should be centered</grid-item>
      <grid-item><img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt=""></grid-item>
      <grid-item><img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt=""></grid-item>
    </grid-container>

    Note that for vertical centering, vertical-align: middle will not work.

    This is because the vertical-align property applies only to inline and table-cell containers.

    grid-container {
      display: grid;
      grid-template-columns: 1fr 1fr;
      grid-auto-rows: 75px;
      grid-gap: 10px;
      text-align: center;     /* <--- works */
      vertical-align: middle; /* <--- fails */
    }
    
    
    /* can ignore styles below; decorative only */
    grid-container {
      background-color: lightyellow;
      border: 1px solid #bbb;
      padding: 10px;
    }
    grid-item {
      background-color: lightgreen;
      border: 1px solid #ccc;
    }
    <grid-container>
      <grid-item>this text should be centered</grid-item>
      <grid-item>this text should be centered</grid-item>
      <grid-item><img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt=""></grid-item>
      <grid-item><img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt=""></grid-item>
    </grid-container>

    One might say that display: inline-grid establishes an inline-level container, and that would be true. So why doesn't vertical-align work in grid items?

    The reason is that in a grid formatting context, items are treated as block-level elements.

    6.1. Grid Item Display

    The display value of a grid item is blockified: if the specified display of an in-flow child of an element generating a grid container is an inline-level value, it computes to its block-level equivalent.

    In a block formatting context, something the vertical-align property was originally designed for, the browser doesn't expect to find a block-level element in an inline-level container. That's invalid HTML.


    CSS Positioning

    Lastly, there's a general CSS centering solution that also works in Grid: absolute positioning

    This is a good method for centering objects that need to be removed from the document flow. For example, if you want to:

    Simply set position: absolute on the element to be centered, and position: relative on the ancestor that will serve as the containing block (it's usually the parent). Something like this:

    grid-item {
      position: relative;
      text-align: center;
    }
    
    span {
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
    }
    

    grid-container {
      display: grid;
      grid-template-columns: 1fr 1fr;
      grid-auto-rows: 75px;
      grid-gap: 10px;
    }
    
    grid-item {
      position: relative;
      text-align: center;
    }
    
    span, img {
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
    }
    
    
    /* can ignore styles below; decorative only */
    
    grid-container {
      background-color: lightyellow;
      border: 1px solid #bbb;
      padding: 10px;
    }
    
    grid-item {
      background-color: lightgreen;
      border: 1px solid #ccc;
    }
    <grid-container>
      <grid-item><span>this text should be centered</span></grid-item>
      <grid-item><span>this text should be centered</span></grid-item>
      <grid-item><img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt=""></grid-item>
      <grid-item><img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt=""></grid-item>
    </grid-container>

    Here's a complete explanation for how this method works:

    Here's the section on absolute positioning in the Grid spec: