Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternating CSS Grid columns and mobile view

I am building a list of services for my website using CSS Grid. One of the rows in that overall website grid is broken into two CSS Grid columns.

In the first column of the first row, there is a description of a service. In the second column, there is an image that represents the service.

With each row, the description and image alternate, so on the second row, first column, there is an image, and in the second column, there is a description. Check out the attached image to see what I have working so far (note: I re-sized images to make it easier to take a screenshot).

The mobile version of the CSS Grid is a single column. When I display the same content in the mobile version, the layout no longer works. Since my layout is determined by the HTML content (probably a bad thing, I know), the titles will not always show up above the image, which is what I want. See attached to see the issue.

I believe the answer to solving this problem lies in using flex-direction: row-reverse; however, it is quite hard to come across some good examples (maybe I am just searching the wrong way). The best Codepen I could find does what I want using flex-direction, but it does not nicely place the description in one CSS Grid box and the image in another CSS Grid box, so when resizing the browser, the images overlap the text.. that is probably due to my lack of knowledge using Flexbox (still learning).

Could you help me figure out how to properly create an alternating 2-column list of items that also displays the text and image properly when in a 1-column list?

I would prefer to stay within the CSS Grid/Flexbox/no script world, but I am happy to entertain other ideas.

Thank you very much for any help you can provide!

HTML

<!-- Services area -->
<div class="services-area">
    <div class="services-text">
        <h3>This is service 1</h3>
    </div>
    <div class="services-div">
        <img class="services-image" src="images/home/home-agile-transformation.png" alt="Agile transformation image.">
    </div>
    <div class="services-div">
        <img class="services-image" src="images/home/home-agile-coaching.png" alt="Agile transformation image.">
    </div>
    <div class="services-text">
        <h3>This is service 2</h3>
    </div>
    <div class="services-text">
        <h3>This is service 3</h3>
    </div>
    <div class="services-div">
        <img class="services-image" src="images/home/home-agile-sw-implementation.png" alt="Agile transformation image.">
    </div>
</div>

CSS

// layout for services

// display a stacked grid <767 pixels
.services-area {
    grid-area: svcs;
    display: grid;
    grid-template-columns: 1fr;
    grid-template-rows: auto;

    @if $debug { background-color: $debugServicesArea; }
} 

// display a 2-column grid >768
@include for-size(full-size) {
    .services-area {
    grid-area: svcs;
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto;
    margin-left: $gridMarginLeft;
    margin-right: $gridMarginRight;

    @if $debug { background-color: $debugServicesArea; }
    }
}

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

.services-image {
    max-width: 100%;
    height: auto;
}

Working version of the code in a 2-column layout. Images re-sized so I could take a screen capture. Non-working version when displaying in a mobile 1-column format.

like image 714
Bill Avatar asked Nov 25 '25 21:11

Bill


1 Answers

For accessibility concerns and better SEO keep the markup in the logical order (title, image).

On mobile, you do not need a grid at all, use display:block for the container. Use grid-auto-flow: row dense to fill the grid as densely as possible following the row order. This ensure no grid cell will be empty. Then alternate the title elements by specifying the column they need to start from. You can use the :nth-child() sibling selector to pick the titles, starting from the 3rd and then every 4 (4n - 1 means 4 * 0 - 1 = -1 (invalid sibling, skipping); 4 * 1 - 1 = 3; 4 * 2 - 1 = 7; ...).

/* display a stacked grid <767 pixels */
.services-area {
    display: block;
} 

/* display a 2-column grid >768 */
@media (min-width: 768px) {
  .services-area {
      display: grid;
      grid-template-columns: 1fr 1fr;
      align-items: center;
      justify-content: center;
      grid-auto-flow: row dense;
  }
}

.services-area > :nth-child(4n - 1) {
  grid-column-start: 2;

}

.services-image {
    max-width: 100%;
    height: auto;
}
like image 51
pecus Avatar answered Nov 28 '25 11:11

pecus



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!