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;
}
This helped me:
For example, if you want to reverse the columns on screen lower than 1200px, then in your parent div, use this instead
@media (max-width:1200px) {
.services-area {
display: flex;
flex-flow: column-reverse;
}
}
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;
}


You are a life-saver, thank you! You have no idea how many countless hours I was trying to figure this out! A quick follow up if you have a moment: is it possible to change the text as well? For example, rather than the text be centered, it would be left-justified on the first row and right-justified on the second row? I understand how to style it, just not if I can use this method to alternate the styling. Anyway, thanks again!!
Sure. Use the same