Re-order blocks inside bootstrap columns using grid css - css

I have two columns and each column contains two blocks
The current order in mobile is
1
2
3
4
And I want it to be :
3
1
2
4
I tried to use grid but I don't know how I can get block 3 out from column 2.
See:
body {
padding-top: 50px;
}
.block {
padding: 40px;
text-align: center;
}
.y{
background:yellow;
}
.r{
background:red;
}
.b{
background:lightblue;
}
.g{
background:lightgreen;
}
#media only screen and (max-width: 991px) {
.container {
display: grid;
background-color: pink;
}
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<div class="col-md-8">
<div class="block y"> 1</div>
<div class="block r">2 </div>
</div>
<div class="col-md-4">
<div class="block b"> 3</div>
<div class="block g">4 </div>
</div>
</div>
And another question can we did this ordering by using CSS supported by IE11? because display:grid is not supported by IE.

Change the layout a little and you will be able to achieve this using bootstrap classes (https://getbootstrap.com/docs/4.3/utilities/flex/#order) without the need of CSS grid:
body {
padding-top: 50px;
}
.block {
padding: 40px;
text-align: center;
}
.y {background: yellow;}
.r {background: red;}
.b {background: lightblue;}
.g {background: lightgreen;}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
<div class="row">
<div class="col-md-8 order-1 order-md-0">
<div class="block y"> 1</div>
</div>
<div class="col-md-4 order-0 order-md-1">
<div class="block b"> 3</div>
</div>
</div>
<div class="row">
<div class="col-md-8">
<div class="block r">2 </div>
</div>
<div class="col-md-4">
<div class="block g">4 </div>
</div>
</div>
</div>
With you current code, the only way is to use display:contents which is not well supported (https://caniuse.com/#feat=css-display-contents)
body {
padding-top: 50px;
}
.block {
padding: 40px;
text-align: center;
}
.y {
background: yellow;
}
.r {
background: red;
}
.b {
background: lightblue;
}
.g {
background: lightgreen;
}
#media only screen and (max-width: 991px) {
.container {
background-color: pink;
display:flex;
flex-direction:column;
padding:0!important;
}
.container > .row,
.container > .row > div{
display:contents;
}
.b {
order:-1;
}
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
<div class="row">
<div class="col-md-8">
<div class="block y"> 1</div>
<div class="block r">2 </div>
</div>
<div class="col-md-4">
<div class="block b"> 3</div>
<div class="block g">4 </div>
</div>
</div>
</div>

Related

Adding content into inline-flex div pushes it down [duplicate]

This question already has answers here:
Align inline-block DIVs to top of container element
(5 answers)
Why is this inline-block element pushed downward?
(8 answers)
Closed 1 year ago.
I am trying to order some divs, the idea is that I want to be able to offset them relative to each other to create asymmetrical grid.
All of it is working, until the moment content is added inside.
When a content is added into a div, that div is moved and positioned relative to the content inside it, so that the content is at the top left of the div, I am expecting the opposite behaviour, the div should not move, and the content should move relative to the div.
NOTE: I can not use an outside container to wrap all of them in it.
.column{
width: 49%;
height: 200px;
position: relative;
display: inline-flex;
}
.column:nth-child(2n){
top: 30px;
right: 20px;
}
.column:nth-child(2n - 1){
bottom: 30px;
left: 20px;
}
.red {
background-color: red;
}
.green {
background-color: green;
}
.blue {
background-color: blue;
}
<div class="column red">
<p>
This breaks it
</p>
</div>
<div class="column green">
</div>
<div class="column blue">
</div>
<div class="column red">
</div>
<div class="column green">
</div>
<div class="column blue">
</div>
<div class="column red">
</div>
<div class="column green">
</div>
<div class="column blue">
If possible you could achieve the expected behavior by wraping the content inside another div and positioning it using position: absolute
.column{
width: 49%;
height: 200px;
position: relative;
display: inline-flex;
}
.column:nth-child(2n){
top: 30px;
right: 20px;
}
.column:nth-child(2n - 1){
bottom: 30px;
left: 20px;
}
.red {
background-color: red;
}
.green {
background-color: green;
}
.blue {
background-color: blue;
}
.column > div {
position: absolute
}
<div class="column red">
<div>
<p>
This breaks it
</p>
</div>
</div>
<div class="column green">
</div>
<div class="column blue">
</div>
<div class="column red">
</div>
<div class="column green">
</div>
<div class="column blue">
</div>
<div class="column red">
</div>
<div class="column green">
</div>
<div class="column blue">
Why don't you use the old pal float. I still use it over flex and grid often. much easier when simple layouts-
* {box-sizing:border-box;}
.column{
width: 50%;
height: 200px;
float:left;
position:relative;
}
.column:nth-child(2n){
top: 30px;
right: 20px;
}
.column:nth-child(2n - 1){
bottom: 30px;
left: 20px;
}
.red {
background-color: red;
}
.green {
background-color: green;
}
.blue {
background-color: blue;
}
<div class="column red">
<p>
This breaks it
</p>
</div>
<div class="column green">
</div>
<div class="column blue">
</div>
<div class="column red">
</div>
<div class="column green">
</div>
<div class="column blue">
</div>
<div class="column red">
</div>
<div class="column green">
</div>
<div class="column blue">
Note: I add box-sizing rule becouse I hate that width:49%

CSS Display: Flex on Desktop and Mobile

I'm newer to using FLEXBOX and have a question on a layout using Desktop and Mobile.
I'm displaying info using a label and data (not on a form).
On the desktop, I'd like it to display like this:
label-------label-------label------label
Data--------Data--------Data-------Data
On a desktop, label and data will be a % based on number of elements.
But, on a mobile, I'd like it to display like this:
label------
Data-------
Label------
Data-------
label------
data-------
Label------
Data-------
label------
data-------
On mobile, I'd like label and data to be 25% & 75% wide.
Not sure on the HTML if it should be laid out like this
<div class="container">
<div class="label">Label</div>
<div class="data">Data</a>
<div class="label">Label</div>
<div class="data">Data</a>
<div class="label">Label</div>
<div class="data">Data</a>
</div>
OR
<div class="container">
<div class="label">label</div>
<div class="label">label</div>
<div class="label">label</div>
</div>
<div class="container">
<div class="data">data</div>
<div class="data">data</div>
<div class="data">data</div>
</div>
Any guidance would be great!
Thanks!
It sounds like you're flexible on the HTML structure.
I recommend grouping data pairs with parent elements, making columns and rows.
With two nested flexboxes, you can change flex-direction as desired.
/* FOR DEMO PURPOSES */
var $body = $('body');
$('button').on('click', function() {
$body.toggleClass('small');
});
.container {
display: flex;
flex-wrap: wrap;
background-color: lightgreen;
}
.group {
display: flex;
flex-direction: column;
}
.item {
padding: .25em .5em;
}
#media (min-width: 700px) {
.container {
background-color: lightblue;
flex-direction: column;
}
.group {
flex-direction: row;
}
}
/* FOR DEMO PURPOSES */
.small .container {
background-color: lightblue;
flex-direction: column;
}
.small .group {
flex-direction: row;
}
button {
position: absolute;
top: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="group">
<div class="item label">Label 1</div>
<div class="item data">Data 1</div>
</div>
<div class="group">
<div class="item label">Label 2</div>
<div class="item data">Data 2</div>
</div>
<div class="group">
<div class="item label">Label 3</div>
<div class="item data">Data 3</div>
</div>
</div>
<button>Simulate Size Change</button>
Here's a demo with more than one row of data:
/* FOR DEMO PURPOSES */
var $body = $('body');
$('button').on('click', function() {
$body.toggleClass('small');
});
.container {
display: flex;
flex-wrap: wrap;
background-color: lightgreen;
}
.group {
display: flex;
flex-direction: column;
}
.item {
padding: .25em .5em;
}
.label {
font-weight:bold;
}
.flag {
color:red;
}
#media (min-width: 700px) {
.container {
background-color: lightblue;
flex-direction: column;
}
.group {
flex-direction: row;
}
}
/* FOR DEMO PURPOSES */
.small .container {
background-color: lightblue;
flex-direction: column;
}
.small .group {
flex-direction: row;
}
button {
position: absolute;
top: 130px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="group">
<div class="item label">Label 1</div>
<div class="item data">Data 1a</div>
<div class="item data flag">Data 1b</div>
<div class="item data">Data 1c</div>
</div>
<div class="group">
<div class="item label">Label 2</div>
<div class="item data">Data 2a</div>
</div>
<div class="group">
<div class="item label">Label 3</div>
<div class="item data">Data 3a</div>
<div class="item data">Data 3b</div>
</div>
</div>
<button>Simulate Size Change</button>
For more ideas, I highly recommend reading Accessible, Simple, Responsive Tables # CSS-Tricks and checking out the other resources listed there.
I would order them like the first option. Then, at desktop view I'd make a flex flow of column wrap, set a height for the container and set each flex-item to be 50% height.
On mobile, id switch to flex-flow: row wrap, and define the container's width, then each child at 25%/75% depends on which child.
HTML:
<div class="container">
<div class="label">Label</div>
<div class="data">Data</a>
<div class="label">Label</div>
<div class="data">Data</a>
<div class="label">Label</div>
<div class="data">Data</a>
</div>
CSS:
.container {
display: flex;
flex-flow: row wrap;
justify-content: space-evenly;
align-items: center;
height: 500px; // what ever you want here
}
.label, .data {
height: 45% // Less than 50% for margins, etc.
}
#media only screen and (max-width: 900px) { //Set desired width to call 'mobile'
.container {
flex-flow: row wrap;
width: unset;
height: 500px; //Whatever you want again
}
.data {
width: 70%;
}
.label {
width: 22%;
}
}

How to make div expand with content using flex?

I have this HTML and CSS:
.container {
width: 100%;
}
.group {
display: flex;
justify-content: space-between;
min-width: 214px;
background: #eee;
}
.abbr {
/* some styling */
}
.name {
/* some styling */
}
<div class="container">
<div class="group">
<div class="abbr">
<p>MS</p>
</div>
<div>
<p class="name">Mark Smith</p>
</div>
</div>
</div>
Now, if I use just min-width, the whole div stretches as the entire width of the container. If I just use width, it won't expand if the name is longer than Mark Smith (rather it will go to the next line).
This is what I wanted to achieve:
How do I achieve this in flexbox?
What you're looking for is to apply width: fit-content to .group.
Then you can adjust the offset between the abbreviation and name with min-width on the .abbr.
This can be seen in the following:
.group {
display: flex;
width: fit-content;
background: #eee;
margin: 10px 0;
}
.group > div {
margin: 0 10px;
}
.abbr {
min-width: 50px;
}
<div class="container">
<div class="group">
<div class="abbr">
<p>MS</p>
</div>
<div>
<p class="name">Mark Smith</p>
</div>
</div>
<div class="group">
<div class="abbr">
<p>MS</p>
</div>
<div>
<p class="name">A Really Really Long Name</p>
</div>
</div>
</div>
I use inline-block on .container so that it won't take up the whole line.
.container {
display: inline-block;
}
.group {
display: flex;
background: #eee;
}
.abbr {
padding: 0 7px;
}
.name {
padding: 0 7px;
}
<div class="container">
<div class="group">
<div class="abbr">
<p>MS</p>
</div>
<div>
<p class="name">Mark Smith</p>
</div>
</div>
</div><br/><br/>
<div class="container">
<div class="group">
<div class="abbr">
<p>MR</p>
</div>
<div>
<p class="name">Loooooooooooooooong Name</p>
</div>
</div>
</div>
Another solution is to use a third element that consume all the remaining space and set the background color on the text content only:
.container {
margin: 0 0 5px 0;
}
.group {
display: flex;
}
.abbr {
padding: 0 7px;
background: #eee;
}
.name {
padding: 0 7px;
background: #eee;
flex: 0 0 auto;
}
.blank-space{
flex: 1 1 auto;
}
<div class="container">
<div class="group">
<div class="abbr">
<p>MS</p>
</div>
<div class="name">
<p>Mark Smith</p>
</div>
<div class="blank-space"></div>
</div>
</div>
<div class="container">
<div class="group">
<div class="abbr">
<p>MR</p>
</div>
<div class="name">
<p>Loooooooooooooooong Name</p>
</div>
<div class="blank-space"></div>
</div>
</div>

Bootstrap Altering a child div in a row

Here is my html:
<div class="container-fluid">
<div class="row">
<div class="col-sm-6 div1">DIV1</div>
<div class="col-sm-6 div2">DIV2</div>
<div class="col-sm-6 div3">DIV3</div>
<div class="col-sm-6 div4">DIV4</div>
</div>
</div>
Here is my css:
.row div{
height: 100px;
}
.div1{
background: blue;
}
.div2{
background: red;
}
.div3{
background: darkcyan;
}
.div4{
background: cyan;
}
Its ok in normal view
Is it possible to alter div4 with div3 on mobile view like below image
You can swap the color of div3 and div4 using media query for mobile min-width: 767px
.row div{
height: 100px;
}
.div1{
background: blue;
}
.div2{
background: red;
}
.div3{
background: darkcyan;
}
.div4{
background: cyan;
}
#media(max-width:767px){
.div3{
background: cyan;
}
.div4{
background: darkcyan;
}
}
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div class="container-fluid">
<div class="row">
<div class="col-sm-6 div1"></div>
<div class="col-sm-6 div2"></div>
<div class="col-sm-6 div3"></div>
<div class="col-sm-6 div4"></div>
</div>
</div>

Make a div get to the top of another div

I'm making a template, and I'd like to have a div that his height gets to the top of another div. A screenshot that explains it a bit:
This is my CSS:
.grid_1 { width:60px; }
.grid_2 { width:140px; }
.grid_3 { width:220px; }
.grid_4 { width:300px; }
.grid_5 { width:380px; }
.grid_6 { width:460px; }
.grid_7 { width:540px; }
.grid_8 { width:620px; }
.grid_9 { width:700px; }
.column {
margin: 0 10px;
overflow: hidden;
float: left;
display: inline;
}
.row {
width: 720px;
margin: 0 auto;
overflow: hidden;
}
.row .row {
margin: 0 -10px;
width: auto;
display: inline-block;
}
And HTML:
<div class="row">
<div class="column grid_9"><p><img src="img/bomb.gif" style=" margin-bottom: 10px; padding-right: 5px; padding-left: 5px; padding-bottom: 5px; padding-top: 5px;">
</p></div>
</div>
<div class="row">
<div class="column grid_3"><p style="line-height: 222px;">TEST</p></div>
<div class="column grid_6"><p>post</p></div>
<div class="column grid_6"><p>post</p></div>
<div class="column grid_6"><p>post</p></div>
</div>
<div class="row">
<div class="column grid_3"><p>footer</p></div>
<div class="column grid_3"><p>footer</p></div>
<div class="column grid_3"><p>footer</p></div>
</div>
jsFiddle link
jsFiddle
<div class="row">
<div class="column grid_9">
<img src="img/bomb.gif" style="margin-bottom: 10px; padding: 5px;">
</div>
</div>
<div class="row">
<div class="column grid_3"><p style="line-height: 222px;">TEST</p></div>
<div style="overflow: hidden">
<div class="column grid_6"><p>post</p></div>
<div class="column grid_6"><p>post</p></div>
<div class="column grid_6"><p>post</p></div>
</div>
</div>
<div class="row">
<div class="column grid_3"><p>footer</p></div>
<div class="column grid_3"><p>footer</p></div>
<div class="column grid_3"><p>footer</p></div>
</div>
Just use .grid_6{float: right} and it should work.
Update:
A practice that I use is that I wrap such three divs in another div. I would do something like
<div style="overflow: hidden">
<div style="float: left">TEST</div>
<div style="float: right; overflow: hidden">
<div>POST</div>
<div>POST</div>
<div>POST</div>
</div>
</div>
I guessed:
.grid_3 {
position: relative;
z-index: 100;
}
This answer was originally by Eric:
jsFiddle working
If you want to align the last post to the right, you can do a couple things
float:right; //may require parent to also float
text-align:right; //to parent container
right:0px; // need to change position first I believe
margin-left:auto; // should push it to the right all the way
margin-left:123px; //fixed amount

Resources