11

These are 3 inline-block and elements which means that they will be ordered next to each other.

Here is a fiddle to view everything live: https://jsfiddle.net/8mdm8eox/

.wrapper {
  background: #fff;
  width: 100%
}

.firstElement,
.secondElement,
.thirdElement {
  display: inline-block;
  width: calc(100%/3)
}

.firstElement {
  background: #000;
  color: #fff
}

.secondElement {
  background: grey
}

.thirdElement {
  background: #ddd
}

@media (max-width: 767px) {}
<div class="wrapper">
  <div class="firstElement">First Element</div>
  <div class="secondElement">Second Element</div>
  <div class="thirdElement">Third Element</div>
</div>

So here is what I want , I want when the screen width is 767px or less:

@media (max-width: 767px){}

The first two elements are ordered vertically and the third one is ordered horizontally with the two other elements, So that they become like:

   _______________    ________________
   |First Element|    |ٍ              |
   _______________    |              |  
                      |Third Element |
   ________________   |              |
   |Second Element|   |              |
   _________________  _______________

Don't worry about the third element , The text will be broken , I just want the first two elements to look like that without changing the html.

Dhaval Jardosh
  • 7,151
  • 5
  • 27
  • 69
Frank
  • 115
  • 1
  • 8

5 Answers5

5

There are various ways to re-order your elements without altering the HTML.

CSS flexbox provides the order property. However, flex may not be a good option for you since you want one element to span two rows. The problems you may encounter are discussed here:

CSS grid layout, however, offers many good solutions to your problem. The order property is also available here, but it's not necessary.

Here's one solution using the grid-template-areas property.

.wrapper {
  display: grid;
  grid-gap: 5px;
  grid-template-areas: "first second third";
}

.firstElement {
  grid-area: first;
  background: #000;
  color: #fff
}

.secondElement {
  grid-area: second;
  background: grey
}

.thirdElement {
  grid-area: third;
  background: #ddd
}

@media (max-width: 767px) {
  .wrapper {
    grid-template-areas: "first third" 
                         "second third";
  }
<div class="wrapper">
  <div class="firstElement">First Element</div>
  <div class="secondElement">Second Element</div>
  <div class="thirdElement">Third Element</div>
</div>

jsFiddle demo

Browser support for CSS Grid.

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
2

You need to use flex-wrap on the .wrapper and order on children.

.wrapper {
  max-width: calc(100%/2);  //Just to keep your original width intact
  display: flex;
  flex-wrap:wrap;
}

.firstElement, .secondElement, .thirdElement{
    min-width:50%; //This will force your width to 50% of your wrapper class
}
.firstElement{ order: 1;}
.secondElement{ order: 2;}
.thirdElement{ order: 3;}

.wrapper {
  background: #fff;
  max-width: calc(100%/2);
  display: flex;
  flex-wrap: wrap;
}

.firstElement,
.secondElement,
.thirdElement {
  display: inline-block;
  min-width: 50%
}

.firstElement {
  background: #000;
  color: #fff;
  order: 1;
}

.secondElement {
  background: grey;
  order: 3;
}

.thirdElement {
  background: #ddd;
  order: 2;
}

@media (max-width: 767px) {}
<div class="wrapper">
  <div class="firstElement">First Element</div>
  <div class="secondElement">Second Element</div>
  <div class="thirdElement">Third Element</div>
</div>
Dhaval Jardosh
  • 7,151
  • 5
  • 27
  • 69
0

If you do not want to use flex, the table-layout properties can help .

play with https://codepen.io/gc-nomade/pen/yjrOJJ or just run demo below.

.wrapper {
  background: #fff;
  width: 100%;
}

.firstElement,
.secondElement,
.thirdElement {
  display: inline-block;
  min-width: 33%;/* will be usefull for the mediaquerie . tune to your own value / needs */
  margin: 0.11%;/* if ever needed */
}

.firstElement {
  background: #000;
  color: #fff;
}

.secondElement {
  background: grey;
}

.thirdElement {
  background: rgba(0, 0, 0, 0.3);
}

@media (max-width: 767px) {
  .wrapper {
    display: table;/* trigger the table-layout */
  }
  .a {
    display: block;
    margin: 2px;
  }
  .b {
    display: table-cell;/* make this one only acting as a cell aside previous */
  }
}
<div class="wrapper">
  <div class="firstElement a">First Element</div><!-- comment to override inline-block side effect 
  --><div class="secondElement a">Second Element</div><!--
  --><div class="thirdElement b">Third Element</div>
</div>

For real reordering, flex or grid will do it within any amount of children.

The table-layout properties allows this visual effect on a single row but works with old browsers.

G-Cyrillus
  • 101,410
  • 14
  • 105
  • 129
0

Since the question isn't tagged with flex or new tech, nor included it in the source code, this is one solution reflecting that:

*Please note, I changed the width of the elements to 100%/3.1 for visual effect, you can change it to suit your needs.

.wrapper {
  background: #fff;
  position: relative;
  width: 100%;
  height: 500px;
}

.firstElement,
.secondElement,
.thirdElement {
  display: inline-block;
  width: calc(100%/3.1)
}

.firstElement {
  background: #000;
  color: #fff;
  height: 33%;
}

.secondElement {
  background: grey;
  height: 33%
}

.thirdElement {
  background: #ddd;
  height: 33%
}

@media (max-width: 767px) {
  .firstElement, .secondElement, .thirdElement {
    width: 50%;
  }
  .firstElement {
    float: left;
  }
  .secondElement {
    position: absolute;
    left: 0;
    bottom: 0;
  }
  .thirdElement {
    float: left;
    height: 100%;
  }
}
<div class="wrapper">
  <div class="firstElement">First Element</div>
  <div class="secondElement">Second Element</div>
  <div class="thirdElement">Third Element</div>
</div>

Essentially, making the wrapper position relative gives us the freedom of absolute positioning inside of it for children. We can take advantage of that

soulshined
  • 9,612
  • 5
  • 44
  • 79
0

You can do it easily with the positioning, which has great support, and optionally combined with the CSS variables, whose support is increasing and isn't little by any means:

:root {
  --firstElementHeight: 50px; /* adjust */
  --secondElementHeight: 50px; /* adjust */
  --thirdElementHeight: calc(var(--firstElementHeight) + var(--secondElementHeight)); /* the sum of other siblings heights so that the "columns" always match */
}

.firstElement,
.secondElement,
.thirdElement {display: inline-block; width: 33.33%}

.firstElement {background: #000; color: #fff}
.secondElement {background: grey}
.thirdElement {background: #ddd}

@media (max-width: 767px) {
  .wrapper {position: relative}
  .firstElement {height: var(--firstElementHeight)}
  .secondElement {height: var(--secondElementHeight); position: absolute; left: 0; top: var(--firstElementHeight)} /* moved down by the height of the .firstElement */
  .thirdElement {height: var(--thirdElementHeight)}
}
<div class="wrapper">
  <div class="firstElement">First Element</div>
  <div class="secondElement">Second Element</div>
  <div class="thirdElement">Third Element</div>
</div>

Even without CSS variables, the positioning solution is fairly simple and reliable.

VXp
  • 11,598
  • 6
  • 31
  • 46