1

I am currently in the process of building a search results page using Flexbox/CSS.

My requirements are that:

  • Results should be displayed in a grid
  • Responsive, with the number of columns varying from 1-3 based on screen size
  • Results should maintain a 1:1 aspect ratio
  • Results should will the width of the screen evenly
  • Results should wrap
  • Certain featured results to occasionally take up the size of 2 x 2 relative the size of the grid - this will only happen once every 20-30 results so no featured results would ever overlap

I am having trouble figuring out the last requirement, and if there's any possible way to make it work using pure CSS without involving JavaScript.

Please note that there are many answers on StackOverflow on how to do this with either colspan or rowspan, but not both. Those answers often involve setting up my grid to load rows from top-to-bottom, rather than left-to-right, which I also don't want.

Current:

current layout

What I want (see yellow):

layout with featured results

I was able to get everything but my last requirement to work in CSS with the following code:

HTML (simplified):

<div class="products">
    <div class="product">
        <div class="content">
            <img/>
        </div>
    </div>

    <div class="product">
        <div class="content">
            <img/>
        </div>
    </div>

    <div class="product">
        <div class="content">
            <img/>
        </div>
    </div>

    [...and so on...]

</div>

SCSS:

// From bootstrap 4:
$grid-breakpoints: (
    xs: 0,
    sm: 576px,
    md: 768px,
    lg: 992px,
    xl: 1200px
) !default;

@mixin media-breakpoint-up($name) {
  @if $name == xs {
    @content;
  } @else {
    @media screen and (min-width: map-get($grid-breakpoints, $name)) {
      @content;
    }
  }
}

// Variables:
$gap: 1rem;
$background-color: white;

// Results:
.products {
    // Parent flex layout
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    margin: -#{$gap} 0 #{$gap} -#{$gap};

    .product {
        // Child flex layout
        flex: 1 1 auto;
        position: relative;
        &:before {
            content: '';
            display: block;
            padding-top: 100%;
        }
        margin: #{$gap} 0 0 #{$gap};

        // Background
        background-color: $background-color;
        background-repeat: no-repeat;
        background-position: center;

        // Number of columns based on screen size
        @include media-breakpoint-up(sm) {
            width: calc(100% - #{$gap});
            max-width: calc(100% - #{$gap});
        }
        @include media-breakpoint-up(md) {
            width: calc(50% - #{$gap});
            max-width: calc(50% - #{$gap});
        }
        @include media-breakpoint-up(lg) {
            width: calc(33.33% - #{$gap});
            max-width: calc(33.33% - #{$gap});
        }
        @include media-breakpoint-up(xl) {
            width: calc(25% - #{$gap});
            max-width: calc(25% - #{$gap});
        }

        .content {
            // Maintain aspect ratio
            position: absolute;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;

            > img {
                // Restrict to size of parent container
                max-width:100%;
                max-height:100%;
                // Center horizontally and vertically
                position: absolute;
                top: 50%;
                left: 50%;
                transform: translate(-50%, -50%);
            }
        }
    }
}
Anton
  • 3,998
  • 25
  • 40
  • https://stackoverflow.com/q/42946454/3597276 – Michael Benjamin Dec 24 '17 at 15:49
  • @Michael_B That question only works for either colspan or rowspan, but not both. I've come across a few answers like that one on SO, but nothing where both work. – Anton Dec 24 '17 at 15:51
  • 4
    The underlying message of that post is that flexbox is not designed for 2-dimensional grids (rowspan / colspan). It's designed only for aligning items along 1 dimension (rows or columns). Here's a more detailed explanation: https://stackoverflow.com/q/44377343/3597276 – Michael Benjamin Dec 24 '17 at 15:54
  • 1
    You definitely need CSS Grid for that. What you're trying to do it not possible with Flexbox without JS or lots of breakpoints, i.e. no automation for this one. Your design is based around two dimensions (X and Y), whilst Flexbox has only one (X OR Y). – CyberAP Dec 24 '17 at 17:35

0 Answers0