Theming a Drupal 8 View with CSS Grid
Some different modules and plugins can alter the display of a view in Drupal, for instance, to alternate the order of image and text every new row, or to build some kind of stacked layout.
It is possible to alter the display of a view with just some lines of CSS code instead. This approach has many advantages, being the fact of not having to install and update a module, the most relevant one.
Keep reading to learn how!
Step #1. – The Proposed Layout
As you can notice, we can divide the layout into six columns and five rows. There are empty cells in the grid, whereas other cells contain one item of the view across many cells (grid area). The Drupal view shows a list of articles and their titles. The view format is unformatted list.
Step #2. – Create an Image Style
To ensure that all images are squared, it is necessary to configure an image style and set it as display style in the view.
- Click Configuration > Image styles
- Click Add image style
- Give the new image style a proper name, for example, Crop 600×600.
It is always a good idea to include some reference about the dimension or the proportion of the image style. That helps when having multiple image styles configured.
- Click Create new style
- Select Crop from the dropdown
- Click Add
- Set height and width for the crop effect (make sure both dimensions are equal)
- Leave the default crop anchor at the center of the image
- Click Add effect
- Make sure the image effect was recorded properly and click Save
Step #3. – Create the View
- Create 11 article nodes in your Drupal installation with their images
- Click Structure > Views > Add view
- Initial settings:
- Content of type Article
- Create a block
- Unformatted list of fields
- 11 items per block
- Click Save and edit
- In the FIELDS area click Add
- Type image in the search box
- Check it
- Click Add and configure fields
- Exclude this field from display
- Change the Image style
- Link the image to the content
- Click Apply
- Rearrange the fields, so that the Image field is above
- Click Apply
- Click on the Title field to edit it
- Display the Style settings
- Check Customize HTML element
- Select SECTION
- Check create a CSS class
- Type gallery-item
- Uncheck Add default classes
- Open the Rewrite results section
- Check Override the output of this field with custom text
- Enter this code:
{{ field_image }}{{ title }}
- Click Apply
You can read more about rewriting results in Views here.
- Save the view
- Click Structure > Block layout
- Scroll down to the Content section
- Click Place block
- Search for your block
- Click Place block
- Uncheck Display title
- Click Save block
- Drag the cross handle and place the block above the Main content
- Scroll down and click Save blocks
Step #4. – Theming the View
There are 3 classes you need to target to apply the layout styles to the view:
-
.gallery-item (each content card will be a grid)
-
#block-views-block-front-gallery-block-1 .view-content
-
#block-views-block-front-gallery-block-1 .view-row
We set the specificity of the CSS styles on the block. The classes .view-content and .view-row are default Views classes. Theming only with these would break the layout of other views on the site, for example, the teaser view on the front page.
Hint: I am working on a local development environment with a subtheme of Bartik. There is much more about Drupal theming at OSTraining here.
If you don’t know how to create a subtheme in Drupal yet, and you are working on a sandbox installation, just add the code at the end of the file and please remember always to clear the cache.
/core/themes/bartik/css/layout.css
Let’s start with the content inside the .gallery-item container. It will be a grid with one column and 4 rows. The image will cover all 4 rows, whereas the title text will be located on the last row. To center the title on its cell, we declare the link tag as a grid container too.
- Edit the CSS code:
.gallery-item { display: grid; grid-template-rows: repeat(4, 1fr); } .gallery-item a:first-of-type { grid-row: 1 / span 4; grid-column: 1; } .gallery-item a:last-of-type { grid-row: 4; grid-column: 1; display: grid; /* Acting as a grid container */ align-content: center; justify-content: center; background-color: rgba(112, 97, 97, 0.5); color: white; font-size: 1.2em; }
Make the images responsive.
- Edit the CSS code:
img { display: block; max-width: 100%; height: auto; }
As already stated, we need a grid with 5 rows and 6 columns. After declaring it, map every position in the grid according to the layout with an area name. The empty cells/areas will be represented with a period.
- Edit the CSS code:
#block-views-block-front-gallery-block-1 .view-content { display: grid; grid-template-columns: repeat(6, 1fr); grid-template-rows: repeat(5, 1fr); grid-gap: 0.75em; grid-template-areas: ". thumb1 main main main thumb2" ". thumb3 main main main thumb4" ". thumb5 main main main thumb6" "secondary secondary thumb7 thumb8 thumb9 ." "secondary secondary . . . ."; max-width: 70vw; margin: 0 auto; }
Now it’s time to assign each grid item to its corresponding region.
- Edit the CSS code:
#block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(1) { grid-area: main; } #block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(2) { grid-area: secondary; } #block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(3) { grid-area: thumb1; } #block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(4) { grid-area: thumb3; } #block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(5) { grid-area: thumb5; } #block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(6) { grid-area: thumb2; } #block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(7) { grid-area: thumb4; } #block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(8) { grid-area: thumb6; } #block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(9) { grid-area: thumb7; } #block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(10) { grid-area: thumb8; } #block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(11) { grid-area: thumb9; }
I think this is a practical way to layout Views items the way you want without the need of installing extra modules, which could unnecessarily affect the performance of your site.
The Media Queries
The layout will break at around 970px, because of the font size.
- Edit the CSS code:
@media screen and (max-width: 970px) { .views-row > div .gallery-item > a:nth-child(2) { font-size: .9em; } }
To change the layout, just add a media query with a new grid-template-areas distribution, and of course, we have to change the way the rows and columns are distributed The items are already assigned to their respective areas.
- Edit the CSS code:
@media screen and (max-width: 700px) { .view-content { grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(10, auto); grid-template-areas: "main main" "main main" "thumb1 thumb2" "thumb3 thumb4" "secondary secondary" "secondary secondary" "thumb5 thumb6" "thumb7 thumb8" "thumb9 thumb9" "thumb9 thumb9"; } }
This layout will work even with the smallest device screen.
I hope you liked this tutorial. Thanks for reading!
Hi, is it possible to use different image styles for the different sized images?
Hi Eric,
Sure it is possible, in that case you wouldn’t need a layout with squares but a layout with rectangles.
That’s the whole point of the technique. If you know how the layout is going to look, then you take the original image from each post (I’m assuming here the image has the right aspect ratio).
It is possible to create different image styles to crop the image before adding it to the post, but that is kind of unnecessary work, considering a unique layout at a time.
Views assigns one image style to all images in the display, so that is not possible within Views.
https://drive.google.com/file/d/13e72sfHKJu_s41-9DbsMRCcoznvXWCuD/view?usp=sharing
Regards
Hi, I want to ask you how to apply different image styles to a list of images in a view, the first image of the result is larger than the others.