potato
potato

Reputation: 79

How can I Stack Divs above each other when the screen is small?

There's five divs. They're all next to each other but they get all weird and stuff when viewed on a mobile device. How can I stack these divs above each other only when the screen size isn't big enough to display them side by side?

#a,
#b,
#c,
#d,
#e {
  background-color: cyan;
  width: 300px;
  height: 500px;
  margin: 10px;
  border-radius: 5%;
}

#wee {
    display: flex;
}
<div id="wee">
  <div id="a">
    stuff
  </div>

  <div id="b">
    weeeeeee
  </div>

  <div id="c">
    i like turtles
  </div>

  <div id="d">
    i don't eat sunglasses.

  </div>

  <div id="e">
    cough cough
  </div>
</div>

The divs are all colored and 300px wide, 500px tall.

Upvotes: 0

Views: 1465

Answers (3)

David Thomas
David Thomas

Reputation: 253308

While your question has been answered already, the solution that was accepted fails the requirement presented in the comments to your question:

when the size of the screen isn't enough to show the divs side by side, [I] want the divs to be stacked one on top of the other … [I] want the size to remain as [they area].

While the statement is perhaps somewhat ambiguous, I read this to mean that you want the elements – #a,#b, #c, #d and #e – to remain 300px in width and 500px in height.

So, while you've accepted that answer, I thought it might be worthwhile offering an alternative which does retain the desired width and height:

// This JavaScript is used to show how the elements are sized and resized
// in the demo; this is not required in production but is merely to give
// information in the rendered demo page:
let wee = document.querySelector('#wee'),
  cards = wee.querySelectorAll('div[id]'),
  wGCS = window.getComputedStyle,
  fauxResize = new Event('resize');

window.addEventListener('resize', (e) => {
  let parentSizing = [wGCS(wee, null).height, wGCS(wee, null).width];
  cards.forEach(
    (div) => {
      let dimensions = [wGCS(div, null).height, wGCS(div, null).width, ...parentSizing];

      div.querySelectorAll('li').forEach(
        (li, i) => li.textContent = dimensions[i]
      )

    });
});
window.addEventListener('DOMContentLoaded', (e) => {
  cards.forEach(
    (div) => {
      let clone = document.querySelector('template').content.cloneNode(true);
      div.appendChild(clone);
    });
  window.dispatchEvent(fauxResize);
});
#a,
#b,
#c,
#d,
#e {
  background-color: cyan;
  /* while the default-value of flex-direction is 'row'
     it's worth stating it to ensure your layout is
     as you expect: */
  flex-direction: row;
  /* flex-grow and flex-shrink properties are both 0 so
     that the flex layout algorithm does not resize them: */
  flex-grow: 0;
  flex-shrink: 0;
  /* I've removed the 'width' declaration, and replaced it
     with flex-basis: */
  flex-basis: 300px;
  /* as the flex-direction is 'row' the flex-layout will
     take care of the width in that axis, but the cross-
     axis height should be stated: */
  height: 500px;
  border-radius: 5%;
}

#wee {
  display: flex;
  /* we use 'gap' here to set the 10px 'gutter' between
     adjacent elements: */
  gap: 10px;
  /* and padding to move the elements 10px from the
     borders of the parent: */
  padding: 10px;
}


/* when the width is less than 1550px, which is the minimum
   width required to show the elements with the gaps, widths
   and padding as set in the CSS, we enter the media-query: */
@media screen and (max-width: 1550px) {
  /* setting the flex-direction to column: */
  #wee {
    flex-direction: column;
  }
  #a,
  #b,
  #c,
  #d,
  #e {
    /* here we retain the 0 for both flex-grow and flex-
       shrink; but set 500px as the flex-basis because we wish to preserve
       the height of the elements, and set the width to 300px to preserve
       the width: */
    flex-basis: 500px;
    width: 300px;
  }
}


/* purely aesthetics and for information, to provide information */

*,
::before,
::after {
  box-sizing: border-box;
  font-size: 1rem;
  line-height: 1.5;
  margin: 0;
  padding: 0;
}

ol,
li {
  list-style-type: none;
  color: #ffff;
}

ol {
  background-color: #0006;
}

li {
  display: flex;
  justify-content: space-between;
  width: 80%;
  margin: 0 auto;
}

li[data-title]::before {
  content: attr(data-title);
  display: contents;
}
<!-- this <template> contains an element which displays information in the
     page when rendered, this is for demonstration purposes only, and not
     required in production code -->
<template>
  <ol>
      <li data-title="Height: "></li>
      <li data-title="Width: "></li>
      <li data-title="Parent height: "></li>
      <li data-title="Parent width: "></li>
    </ol>
</template>
<div id="wee">
  <div id="a">stuff</div>
  <div id="b">weeeeeee</div>
  <div id="c">i like turtles</div>
  <div id="d">i don't eat sunglasses.</div>
  <div id="e">cough cough</div>
</div>

JS Fiddle demo.

References:

Upvotes: 1

Rolv Apneseth
Rolv Apneseth

Reputation: 2118

Preferably you shouldn't need to use a media query to achieve this.

All you should need to do with your current set up is add 1 line to your css: flex-wrap: wrap;

So, your full code would look like this:

#a,
#b,
#c,
#d,
#e {
  background-color: cyan;
  width: 300px;
  height: 500px;
  margin: 10px;
  border-radius: 5%;
}

#wee {
    display: flex;
    flex-wrap: wrap;
}
<div id="wee">
  <div id="a">
    stuff
  </div>

  <div id="b">
    weeeeeee
  </div>

  <div id="c">
    i like turtles
  </div>

  <div id="d">
    i don't eat sunglasses.

  </div>

  <div id="e">
    cough cough
  </div>
</div>

However, flex is in general not recommended for multi-line setups, you should just use a grid layout instead:

#a,
#b,
#c,
#d,
#e {
  background-color: cyan;
  height: 500px;
  border-radius: 5%;
}

#wee {
    display: grid;
    grid-template-columns: repeat(auto-fill, 300px);
    grid-gap: 20px;
}
<div id="wee">
  <div id="a">
    stuff
  </div>

  <div id="b">
    weeeeeee
  </div>

  <div id="c">
    i like turtles
  </div>

  <div id="d">
    i don't eat sunglasses.

  </div>

  <div id="e">
    cough cough
  </div>
</div>

Upvotes: 1

Real Quick
Real Quick

Reputation: 2800

You can use this:

<meta name="viewport" content="width=device-width, initial-scale=1.0">

#a,
#b,
#c,
#d,
#e {
  background-color: cyan;
  width: 300px;
  height: 500px;
  margin: 10px;
  border-radius: 5%;
}

#wee {
  display: flex;
}

@media screen and (max-width: 900px) {
  #wee {
    flex-direction: column;
    margin: 10px;
  }
}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<div id="wee">
  <div id="a">
    stuff
  </div>

  <div id="b">
    weeeeeee
  </div>

  <div id="c">
    i like turtles
  </div>

  <div id="d">
    i don't eat sunglasses.

  </div>

  <div id="e">
    cough cough
  </div>
</div>

Upvotes: 1

Related Questions