Flex-wrapping without nested divs - html

I'm trying to make a horizontal card using flexbox without having nested divs.
For example, what I have right now is this:
.card {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.card-img {
width: 37%;
}
.card-content {
width: 63%;
}
<div class='card'>
<div class='card-img'>
<img src='example' />
</div>
<div class='card-content'>
<div class='card-number'>
</div>
<div class='card-type'>
</div>
</div>
</div>
This layout works for now, but when the viewport resizes, I want the horizontal card to change into a vertical one (which it already does). However, I want to re-order the card-img, card-number, and card-type using flex order.
How could I get this same horizontal layout while using this type of div layout?
Edit:
Sorry for the confusing wording, what I was aiming to do was to create a horizontal layout that works like the image except with 3 separate divs, not 2 divs with 1 being a nested div. Sorry!

.card {
display: flex;
}
.card-img {
flex: 0 0 37%;
border: 1px dashed red;
}
.card-number {
flex: 0 0 30%;
border: 1px dashed red;
}
.card-type {
flex: 1 0 30%;
border: 1px dashed red;
}
img {
width: 100%;
}
.card > div {
display: flex;
align-items: center;
justify-content: center;
}
#media (max-width: 500px) {
.card { flex-direction: column; }
.card-img { order: 3; }
.card-number { order: 2; }
.card-type { order: 1; }
}
<div class='card'>
<div class='card-img'>
<img src="http://i.imgur.com/60PVLis.png">
</div>
<div class='card-number'>555</div>
<div class='card-type'>Orange</div>
</div>
https://jsfiddle.net/7y8sarwn/

Related

wrap and stretch inputs on form resize

I have two inputs on form in one row. First one should be stretching on form resize, second is of fixed width. But when form is narrowed to a particular breakpont, second input should wrap to second line and stretch as well as first one.
Is it possible to achieve using CSS?
Tried using grid, but it won't wrap at all.
When using flexbox the result is better, but still have to set flex-grow for second input and it's width is not fixed, while inputs are in one row
.box {
background: grey;
padding: 20px 20px 20px 20px;
}
.wrapper {
display: grid;
grid-column-gap: 6px;
grid-row-gap: 6px;
grid-template-columns: minmax(320px, 1fr) 200px;
}
.flexWrapper {
display: flex;
flex-wrap: wrap;
}
.flex1 {
flex-basis: 320px;
flex-grow: 10;
flex-shrink: 0;
}
.flex2 {
flex-basis: 200px;
flex-shrink: 0;
flex-grow: 1;
}
<div class="wrapper">
<div class="box">One</div>
<div class="box">Two</div>
</div>
<div class="flexWrapper">
<div class="flex1 box">One</div>
<div class="flex2 box">Two</div>
</div>
https://codepen.io/C4off/pen/WNKjJaK
The easiest way to do this is to use a media query. At 600px I've reset the wrapper to be display: block with the children at 100% width which forces them to stack on top of each other. I've set the width of flex2 to 200px to fix it at that.
.box {
background: grey;
padding: 20px 20px 20px 20px;
}
.flexWrapper {
display: flex;
padding-top: 12px;
column-gap: 6px;
row-gap:6px;
}
.flex1 {
flex: 1;
}
.flex2 {
width: 200px;
}
#media only screen and (max-width: 600px) {
.flexWrapper {
display: block;
}
.flex1, .flex2 {
width: 100%;
}
}
<div class="container">
<div class="flexWrapper">
<div class="flex1 box">One</div>
<div class="flex2 box">Two</div>
</div>
</div>
Using flexbox only and the min-width proprty. Note .flex2 will overflow at container widths less than 200px
.container {
width: 60%;
outline: 1px solid red;
}
.box {
background: grey;
padding: 20px 20px 20px 20px;
}
.flex-wrapper {
display: flex;
padding-top: 12px;
column-gap: 6px;
row-gap:6px;
flex-wrap: wrap;
}
.flex1 {
flex: 2 0;
}
.flex2 {
min-width: 200px;
flex-grow: 1;
}
<div class="container">
<div class="flex-wrapper">
<div class="flex1 box">One</div>
<div class="flex2 box">Two</div>
</div>
</div>
The final way this can be done is using container queries which are quite well supported now. The max size is applied to the container and not the screen as the example below
* {
box-sizing:border-box;
}
.container {
container-type: inline-size;
container-name: my-container;
width: 60%;
}
.box {
background: grey;
padding: 20px 20px 20px 20px;
}
.flex-wrapper {
display: flex;
padding-top: 12px;
column-gap: 6px;
row-gap:6px;
}
.flex1 {
flex: 1;
}
.flex2 {
width: 200px;
}
#container my-container (max-width: 600px) {
.container {outline: 1px solid red;}
.flex-wrapper {
display: block;
}
.flex1, .flex2 {
width: 100%;
}
}
<div class="container">
<div class="flex-wrapper">
<div class="flex1 box">One</div>
<div class="flex2 box">Two</div>
</div>
</div>

Responsive CSS: shift middle div rows to a separate column after reaching media query break point

I am using CSS media queries to create a responsive layout.
In my current HTML layout I use flexbox to align rows of divs:
<div id="page">
<div id="div-1">DIV 1</div>
<div id="div-2">DIV 2</div>
<div id="div-3">DIV 3</div>
<div id="div-4">DIV 4</div>
</div>
and CSS:
#page {
display: flex;
flex-direction: column;
align-items: center;
}
[id^="div-"] {
border: 1px solid #ccc;
margin-bottom: 10px;
width: 50vw;
}
#div-1 {
height: 50px;
}
#div-2 {
height: 70px;
}
#div-3 {
height: 150px;
}
#div-4 {
height: 100px;
}
Here is Jsfiddle for you to tinker with.
It is what I am after for a smaller viewports, but would like to switch things around on the next media query break point to have 2 middle divs to shift to a separate column on the right like this:
How do I achieve that? It is pretty obvious for me how to shift last few div rows to another column, but not sure how to tackle the middle rows...
Is there a way to do it by using flexbox or grid?
Another possible solution is to use the order-property in combination with Flexbox (drawback: you'll need a tiny bit of extra html and set the height of the #page container; advantages: flexible div heights and gap sizes):
#page {
display: flex;
flex-direction: column;
align-items: center;
}
[id^="div-"] {
border: 1px solid #ccc;
margin-bottom: 10px;
width: 50vw;
}
#div-1 {
height: 50px;
background: lightgreen;
}
#div-2 {
height: 70px;
background: lightyellow;
}
#div-3 {
height: 150px;
background: lightcoral;
}
#div-4 {
height: 100px;
background: lightblue;
}
#media (max-width: 1000px) {
#page {
flex-wrap: wrap;
height: 300px;
}
#small-screen-spacer {
order: 3;
align-self: stretch;
flex: 1 0 100%;
margin-right: 10px;
}
#div-1 {
order: 1;
}
#div-2 {
order: 4;
}
#div-3 {
order: 5;
}
#div-4 {
order: 2;
}
}
<div id="page">
<div id="div-1">DIV 1</div>
<div id="div-2">DIV 2</div>
<div id="div-3">DIV 3</div>
<div id="div-4">DIV 4</div>
<div id="small-screen-spacer"> </div>
</div>
The #small-screen-spacer will fill the entire available vertical space, so that all elements that come after the spacer (defined by the order property) are moved to the second column. Additionally you can set the desired gap between the two columns by setting margin-right on the spacer to your desired value.
Fiddle

Centering a justify-content space-between once it becomes a single column

I am trying to style a div that has two children, with flexbox and flex-wrap, without media-queries, that at a certain width is space-between, but once it is a single column is centered (as opposed to currently where once it wraps it's like flex-start). Hopefully that makes sense.
I think this is the relevant code, basically when it wraps, i would like space between to become center:
HTML and CSS
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 82%;
}
.content h1 {
min-width: 20rem;
}
.content h6 {
min-width: 15.5rem;
}
<div class="content-container">
<div class="content">
<h1>'content1'</h1>
<h6>'content2'</h6>
</div>
</div>
I hope this fits your needs.
Since I don't believe that there is a way to solve your problem using only native CSS (i.e. no media queries, and I assume no JS), I let myself change the space-between to space-around (since you gave .content 82% there is not much of a difference).
if you do not want to use space-around, I find it hard for me to believe that there is a solution without media-queries \ JS.
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
place-items: center;
justify-content: space-around;
width: 100%;
}
h1 {
width: min-content;
}
h6 {
width: min-content;
}
<div class="content-container">
<div class="content">
<h1 class="content__1">'content1'</h1>
<h6 class="content__2">'content2'</h6>
</div>
</div>
Do you want like this:
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: center;
text-align: center;
width: 82%;
}
.content h1 {
min-width: 20rem;
}
.content h6 {
min-width: 15.5rem;
}
<div class="content-container">
<div class="content">
<h1>'content1'</h1>
<h6>'content2'</h6>
</div>
</div>
I'm afraid it's impossible to achieve what you want the way you want (i.e., CSS without a #media query).
Solution 1: CSS without a #media query
If you don’t want to use a #media query, then look at Solution 1. But space-around is a different thing than space-between because space-between will push your two elements all the way to the left and right when they’re not stacked above each other, while space-around will not do so.
An example of space-between:
An example of space-around:
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
width: 82%;
text-align: center;
line-height: 50px;
border: 2px solid red;
}
.content h1 {
min-width: 20rem;
background-color: #DCDCDC;
}
.content h6 {
min-width: 15.5rem;
background-color: #DCDCDC;
}
<div class="content-container">
<div class="content">
<h1>Content 1</h1>
<h6>Content 2</h6>
</div>
</div>
If Solution 1 is good enough for you, then you don’t need to read further. But there are many better options on the table. If you’re not limited and can make changes to your code, then I think you should look at other possible solutions below. You can use different approaches to achieve what you want if you want your two elements to be pushed all the way to the left and right when they’re not stacked above each other.
The reason why this can’t be done without using a #media query, JavaScript or jQuery is that CSS on its own can’t “switch” from space-between to space-around when your two elements get stacked above each other. You need to define some rules using a #media query, JavaScript or jQuery so that CSS will change from space-between to space-around at a specific window width (i.e., exactly when your two elements get stacked above each other). See other possible solutions below.
Solution 2: CSS with a #media query
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 82%;
text-align: center;
line-height: 50px;
border: 2px solid red;
}
.content h1 {
min-width: 20rem;
background-color: #DCDCDC;
}
.content h6 {
min-width: 15.5rem;
background-color: #DCDCDC;
}
#media only screen and (max-width: 708px) {
.content {
justify-content: space-around;
}
}
<div class="content-container">
<div class="content">
<h1>Content 1</h1>
<h6>Content 2</h6>
</div>
</div>
Solution 3: JavaScript
window.onload = function() {
if (window.innerWidth < 709) {
document.getElementById("content").style.justifyContent = "space-around";
} else {
document.getElementById("content").style.justifyContent = "space-between";
}
}
window.onresize = function() {
if (window.innerWidth < 709) {
document.getElementById("content").style.justifyContent = "space-around";
} else {
document.getElementById("content").style.justifyContent = "space-between";
}
}
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
width: 82%;
text-align: center;
line-height: 50px;
border: 2px solid red;
}
.content h1 {
min-width: 20rem;
background-color: #DCDCDC;
}
.content h6 {
min-width: 15.5rem;
background-color: #DCDCDC;
}
<div class="content-container">
<div class="content" id="content">
<h1>Content 1</h1>
<h6>Content 2</h6>
</div>
</div>
Solution 4: jQuery
$(window).on('load', function() {
if ($(window).width() < 709) {
$(".content").css("justify-content", "space-around");
} else {
$(".content").css("justify-content", "space-between");
}
});
$(window).on('resize', function() {
if ($(window).width() < 709) {
$(".content").css("justify-content", "space-around");
} else {
$(".content").css("justify-content", "space-between");
}
});
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
width: 82%;
text-align: center;
line-height: 50px;
border: 2px solid red;
}
.content h1 {
min-width: 20rem;
background-color: #DCDCDC;
}
.content h6 {
min-width: 15.5rem;
background-color: #DCDCDC;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div class="content-container">
<div class="content">
<h1>Content 1</h1>
<h6>Content 2</h6>
</div>
</div>
P.S. I added text-align: center; and line-height: 50px; to the .content class because if you really want to have your content centered then you also need to center text horizontally and vertically inside your containers. This is a quick fix, you can remove that if you want. Also, border: 2px solid red; is added to the .content class so you can better understand the difference between space-between and space-around.
Try this.
.content-container {
display: flex;
justify-content: center;
width: 100%;
text-align:center;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
width: 82%;
text-align:center;
}
.content h1 {
min-width: 20rem;
}
.content h6 {
min-width: 15.5rem;
}
<div class="content-container">
<div class="content">
<h1>'content1'</h1>
<h6>'content2'</h6>
</div>
</div>
Here is an idea using clamp() where I will toggle between a fixed width and full width based on a parameter (50rem in this case)
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 82%;
text-align: center;
}
.content > * {
width: clamp(15rem, (50rem - 100vw)*9999, 100%);
outline: 1px solid red;
}
<div class="content-container">
<div class="content">
<h1>'content1'</h1>
<h6>'content2'</h6>
</div>
</div>
Related article if you want more detail: https://css-tricks.com/responsive-layouts-fewer-media-queries/
The following solution uses only flexbox, no media queries or JavaScript. Does this do what you want?
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 82%;
text-align: center;
}
.content h1,
.content h6 {
flex: 1;
}
.horizontal-spacing {
flex: 1;
min-width: calc(20rem + 15.5rem);
height: 0;
}
<div class="content-container">
<div class="content">
<h1>'content1'</h1>
<span class="horizontal-spacing"></span>
<h6>'content2'</h6>
</div>
</div>

Using Flexbox/Grid in CSS, making images stack on mobile

I'm trying to master the grid layout in CSS3. I want to write some HTML/CSS that enable the my 3x1 grid to stack when viewed on mobile. For now, the squares just keep shrinking until they're small. I've been able to work with mobile CSS before, but working with grids are new to me. Can anyone offer some pointers or suggestions?
Here's my code:
HTML:
<div class="container">
<div class="grid">
<div class="cell">
<img src="https://www.easycalculation.com/area/images/big-square.gif">
</div>
<div class="cell">
<img src="https://www.easycalculation.com/area/images/big-square.gif">
</div>
<div class="cell">
<img src="https://www.easycalculation.com/area/images/big-square.gif">
</div>
</div>
CSS:
.container {
width: 100%;
margin: 0 auto;
}
.grid {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
}
.cell {
flex: 0 0 32%;
margin-bottom: 5px;
}
img {
max-width: 100%;
height: auto;
}
body {
background-color: #dedede;
}
Here's a CodePen link as well: https://codepen.io/anfperez/pen/QrEBLZ
Try this CSS:
(codepen https://codepen.io/bonniemellott/pen/ELypzm)
.container {
width: 100%;
margin: 0 auto;
}
.grid {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.cell {
//removed flex attribute
margin-bottom: 5px;
}
img {
max-width: 100%;
height: auto;
}
body {
background-color: #dedede;
}
Add this to your css
You will have to use media query for stacking the boxes.
The way u can do this is by setting the flex-direction:column on smaller devices
#media (max-width: 768px) { /*You can decrese this number if you want only on small devices*/
.grid {
flex-direction: column;
}
}
Here is the updated codepen link

How to wrap items in flexbox for smaller screens?

I'm trying to create a layout for different resize. I need to reach the result in these images here:
I have this code:
.container {
position: relative;
display: flex;
align-items: stretch;
}
.item {
background-color: black;
box-sizing: border-box;
padding: 20px;
flex: 2;
color: #fff;
}
.item:nth-child(2) {
background-color: grey;
flex: 1
}
.item:nth-child(3) {
background-color: green;
flex: 0.5;
}
#media screen and (max-width: 990px) {
.container {
height: auto;
display: table;
}
.item:nth-child(2) {
float: left;
}
.item:nth-child(3) {
float: right;
}
}
<section class="container">
<div class="item">
<h2>title1</h2>
<hr>You'll notice that even though this column has far more content in it, instead of the other columns ending early, they size themselves to meet the end of this column vertically.</div>
<div class="item">
<h2>title2</h2>
<hr>Normally, the only way to achieve this would be either a hack, or to set all boxes to min-height.
</div>
<div class="item">
<h2>title3</h2>
<hr>This is a column with not much content.
</div>
</section>
Here there's a codepen https://codepen.io/darudev/pen/pyBrzL
Problem is in 990px resize view, I don't find solution to create the same view as "mockup".
Is there someone that can help me or give me some suggestions?
Thank you.
You don't need the table and float properties in your code.
#media screen and (max-width: 990px) {
.container {
height: auto;
display: table;
}
.item:nth-child(2) {
float: left;
}
.item:nth-child(3) {
float: right;
}
}
The entire layout can be made with flexbox.
Here's the solution: When the screen resizes smaller than 990px, allow flex items to wrap and give the first item a 100% width, which forces the following items to the next line.
.container {
display: flex;
}
.item {
background-color: black;
box-sizing: border-box;
padding: 20px;
flex: 2;
color: #fff;
}
.item:nth-child(2) {
background-color: grey;
flex: 1;
}
.item:nth-child(3) {
background-color: green;
flex: 0.5;
}
#media screen and (max-width:990px) {
.container { flex-wrap: wrap; }
.item:first-child { flex-basis: 100%; }
}
<section class="container">
<div class="item">
<h2>title1</h2>
<hr>You'll notice that even though this column has far more content in it,
instead of the other columns ending early, they size themselves to meet the end
of this column vertically.</div>
<div class="item">
<h2>title2</h2>
<hr>Normally, the only way to achieve this would be either a hack, or to set
all boxes to min-height.</div>
<div class="item">
<h2>title3</h2>
<hr>This is a column with not much content.
</div>
</section>
revised codepen