Search code examples
csslayout

Different order items and layout with css3 by resolution with the same html


I don´t manage to get a responsive result keeping the same HTML layout.

I need :

  1. two different block orders if the screen width is before or after 1024px,
  2. => 1024px, I have to display items organized in two columns and make sure blocks 1, 2, 3 are inside the left column and blocks 4, 5 are inside the right column (the height of the wrapper has to fit of the content ),
  3. < 1024px, all blocks are inside unique column but the order is different.

Like this...

1024px and more

enter image description here

1023px and less

enter image description here

Current CSS

@media screen and (max-width: 1023px) {
    .production-container{
        display: grid;
        grid-template-columns: repeat(1, 1fr);
        padding: 0 var(--standard-margin) 0 var(--standard-margin);
        justify-content: stretch;
        min-height: 200px;
    }

    aside.production-block{
        max-width: 100vw;
        width: 100%;
        display: flex;
        flex: 1;
        flex-direction: column;
        margin: 24px 0;
        display: grid;
        grid-template-rows: 1fr auto;
        break-inside: avoid;
    }

    .production-container > .production-block-4 {
        order: 1;
    }

    .production-container > .production-block-1 {
        order: 2;
    }

    .production-container > .production-block-2 {
        order: 3;
    }

    .production-container > .production-block-5 {
        order: 4;
    }

    .production-container > .production-block-3 {
        order: 5;
    }

}

@media screen and (min-width: 1024px) {

   .production-container{
        column-count: 2;
        column-gap: 50px;
        max-width: 1024px;
        background: linear-gradient( var(--text-light-color), var(--text-light-color) ) no-repeat center/1px 100%; /* vertical line in the center */
   }
   .production-block {
        margin: 0 0 10px 0;
        break-inside: avoid;
        max-width: 520px;
    }

}

The most important problem is, in the biggest resolution, I don´t manage to force each block to be on the first or second column, they place thereself naturally based on height content. Maybe, I should change of css strategy compatible with the smallest resolution but when I used "grid", each row got a height that made big blank spaces.

Someone has got an idea ?


Solution

  • You can switch from a grid layout to a column CSS layout (untill masonry CSS grid layout is widely avalaible https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Masonry_Layout , here is an example https://codepen.io/gc-nomade/pen/ExXNXdd For FF at this time if activated)

    Demo from your HTML code in the snippet lower below withouth blank space

    How does it work ?

    • 1 - < 1024px grid for the single column to use order (grid creates a single column if no template is set)

    • 2 - > 1023px column-count and display:block for a 2 column layout . break-after:always & break-before: column will be avalaible for browsers using the chrome engine (see CSS Fragmentation ).

    • 3 - For firefox & >1023px a hudge margin-bottom on the third element, so there can be only 3 on the first column. This margin won't be applied inside the container, npr will be overflowing it, it will only push the fourth on the next column. Firefox can be filtered via (untill it understands break-after:always with Column CSS) to apply the margin trick only for Firefox browsers use :

    @-moz-document url-prefix() {
      .grid > div:nth-child(3) {
       margin-bottom:100%;
       }
    }
    

    Live Example where the main container takes only the height needed to wrap the 2 columns, no matter the height of the children, you will notice that on the second example, where col 2 is taller, Chrome(s) seem follows the breaking rules, the first column do not need to be the tallest one.

    .grid {
      display: grid;
      gap: 1em;
      border:solid;
      background:gray;
        
    }
    
    .grid > div:nth-child(1) {
      order: 1;
    }
    .grid > div:nth-child(2) {
      order: 2;
    }
    .grid > div:nth-child(3) {
      order: 4;
    }
    .grid > div:nth-child(4) {
      order: 0;
    }
    .grid > div:nth-child(5) {
      order: 3;
    
    }
    
    @media (min-width: 1024px) {
      .grid {
        display: block;
        column-count: 2;
      }
      .grid > div {
        margin-bottom: 1em;
      }
      .grid > div:nth-child(3) {
        break-after:always;
      }
      .grid> div:nth-child(4) {
          break-before: column;
          }
      @-moz-document url-prefix() {
        .grid > div:nth-child(3) {
        margin-bottom:100%;/* trick for FF that won't show that margin if the last inside a column but not in the last column */
      }
    }
    }
    
    /* demo */
    .grid {
      counter-reset: divs;
    }
    .grid > div {
      display: grid;
    }
    .grid > div::before {
      counter-increment: divs;
      content: counter(divs);
      color: white;
      margin: auto;
      font-size: clamp(10px, 5vmin, 30px);
    }
    .grid > div:nth-child(1) {
      background: #fa9917;
      height: 100px;
    }
    .grid > div:nth-child(2) {
      background: #33e0fe;
      height: 160px;
    }
    .grid > div:nth-child(3) {
      background: #ff3366;
      height: 80px;
    }
    .grid > div:nth-child(4) {
      background: #2bc940;
      height: 80px;
    }
    .grid > div:nth-child(5) {
      background: #3399fe;
      height: 160px;
    }
    <div class=grid>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
    </div>
    Hello the world
    <hr>
    Make second column taller to see where the fourth stands before you test or ask ;)
    <div class=grid>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div style="height:600px"></div>
    </div>

    Finally, i would advise to use a tiny bit of javascript, or the well known and solid masonry library to avoid that FF CSS tricks. Tricks can become obsolete anytime ;)

    • No idea about Safari behavior about CSS Fragmentation.

    https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fragmentation

    CSS Fragmentation is a module of CSS that defines how content is displayed when it is broken (fragmented) across multiple pages, regions, or columns.

    Fragmentation occurs when an inline box wraps onto multiple lines. It also occurs when a block spans more than one column inside a column layout container, or spans a page break when printed. Each piece of the rendering for the element is called a fragment.

    about the native CSS grid masonry, you can see & read : https://www.smashingmagazine.com/native-css-masonry-layout-css-grid/