Flex layout column width in bootstrap 4 - css

I am trying to break some elements in different order on mobile, i have something like this now
And my html
<main>
<div data-color="yellow"></div>
<div class="wrapper">
<div data-color="orange"></div>
<div data-color="purple"></div>
</div>
</main>
Here is my css
.wrapper {
flex-direction: column;
}
div {
flex: 1;
}
[data-color=purple] {
order: 3;
}
main.mobile {
flex-direction: column;
}
main.mobile .wrapper {
display: contents;
}
main.mobile [data-color=orange] {
order: -2;
}
I made it simple that you can help me, what i need is that now palge lpaut is half and half, i need yellow container to be 75% and right 25%, i am using boostrap 4 but I am not so good at fex layout
Thanks

main {
display: flex;
}
[data-color="yellow"] {
flex: 0 0 75%;
}
.wrapper{
flex: 0 0 25%;
}

you can use flex: 1 percentage(); for example flex: 1 percentage(1/4);
Here I made an example in codepen for you:
https://codepen.io/Alirezaaraby/pen/JjYJMZW?editors=1100

Related

Css Sorting and categorization of random data

Say you have the following data points that are dumped from a database or file, the size of each item representing the amount of something (hours, pizzas, whatever)...
And you would like to organize the data into categories like so using CSS...
How would you do it?
I tried the grid shepard method using grid-rowbut get this instead...
Thanks!
P.S. follow up question... My intuition is that CSS would be faster than JS (...moving each item into the appropriate flexbox that could then sort row members horizontally). Is that true? Is CSS likely to be faster in a dataset of possibly thousands of elements?
You can use the flexbox with order.
This is a guide for the flexbox: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
check this sample:
.wrapper {
display: flex;
flex-flow: row wrap;
}
.wrapper > * {
padding: 10px;
flex: 1 0 100%;
}
.o-1,.o-3,.o-5,.o-7 {
background: gold;
}
.o-2,.o-4,.o-6 {
background: hotpink;
}
.o-1 { order: 1; }
.o-2 { order: 2; }
.o-3 { order: 3; }
.o-4 { order: 4; }
.o-5 { order: 5; }
.o-6 { order: 6; }
.o-7 { order: 7; }
<div class="wrapper">
<aside class="o-1">1</aside>
<aside class="o-3">3</aside>
<aside class="o-2">2</aside>
<aside class="o-4">4</aside>
<aside class="o-7">7</aside>
<aside class="o-5">5</aside>
<aside class="o-6">6</aside>
</div>

Special flexbox layout

I'm trying to accomplish the following layout:
My first thought is to use flexbox to achieve this layout. I currently have the following HTML:
<section>
<div class"item">box1</div>
<div class"item">box2</div>
<div class"item">box3</div>
<div class"item">box4</div>
<div class"item">box5</div>
</section>
How can I achieve the desired layout with my HTML? I can add line break div elements in between items like this as well:
<div class"break"> </div>
Unfortunately I am still not able to achieve the required layout. Please help
A simple CSS-grid based approach would be to use a "template of named grid areas".
CSS grid allows for named areas, which dictate the placement of children based on the grid-area of those grid children. In the case of your requirements, a template based on named areas could be defined as:
grid-template-areas:
"a a b b c c"
". . e f . .";
These template areas work by causing:
child elements with grid-area of a, b, and c to occupy the top row of the template layout, where each spans two columns of the 6 column grid
child elements with grid-area of e and f to occupy the bottom row of the template, at the third and fourth column respectively. The . on this row configuration specifies that no child apples to that area of the template
Note that template area strings can be written on the same line for the grid-template-areas property as shown below:
section {
/* Specify that CSS grid is to be used for layout of children */
display: grid;
/* Specify spacing between children */
grid-gap:1rem;
/* Wrap against six evenly spaced columns of this grid */
grid-template-columns: repeat(6, 1fr);
/* Define the area names of the grid template */
grid-template-areas: "a a b b c c" ". . e f . .";
}
section div:nth-child(1) {
grid-area: a;
}
section div:nth-child(2) {
grid-area: b;
}
section div:nth-child(3) {
grid-area: e;
}
section div:nth-child(4) {
grid-area: f;
}
section div:nth-child(5) {
grid-area: c;
}
/* Optional aesthetics to better match your example */
div {
background: darkgrey;
border-radius: 5px;
color: white;
text-align: center;
}
<section>
<div class "item">box1</div>
<div class "item">box2</div>
<div class "item">box3</div>
<div class "item">box4</div>
<div class "item">box5</div>
</section>
Updates
section {
display: grid;
grid-gap:1rem;
grid-template-columns: repeat(5, auto);
grid-template-areas: "a b c c d e" ". . f g . .";
}
section div:nth-child(1) {
grid-area: a;
}
section div:nth-child(2) {
grid-area: b;
}
section div:nth-child(3) {
grid-area: c;
}
section div:nth-child(4) {
grid-area: f;
}
section div:nth-child(5) {
grid-area: g;
}
section div:nth-child(6) {
grid-area: d;
}
section div:nth-child(7) {
grid-area: e;
}
/* Optional aesthetics to better match your example */
div {
background: darkgrey;
border-radius: 5px;
color: white;
text-align: center;
}
<section>
<div class "item">box1</div>
<div class "item">box2</div>
<div class "item">box3</div>
<div class "item">box4 lots of content causes uneven column distribution</div>
<div class "item">box5</div>
<div class "item">box6</div>
<div class "item">box7</div>
</section>
You Can use CSS Grid Instead:
Complete Grid Guide
Working Demo:
.grid {
display: grid;
grid-template-areas: "i1 i1 i2 i2 i3 i3" ". . i4 i5 . .";
grid-template-columns: repeat(6,1fr); /* to make all boxes same with */
grid-gap: 10px;
}
.i1 {
grid-area: i1
}
.i2 {
grid-area: i2
}
.i3 {
grid-area: i3
}
.i4 {
grid-area: i4
}
.i5 {
grid-area: i5
}
.item {
min-height: 40px;
background-color: #7D7D7D;
border-radius: 10px;
display: flex;
justify-content: center;
;
align-items: center;
color: white;
font-size: 1.5rem;
font-weight: bolder;
}
.i4,.i5 {
border-radius: 8px;
}
<section class="grid">
<div class="item i1">box1</div>
<div class="item i2">box2</div>
<div class="item i3">box3</div>
<div class="item i4">box4</div>
<div class="item i5">box5</div>
</section>
With flexbox you can adjust the order of the element and rely on wrapping:
section {
display:flex;
flex-wrap:wrap;
justify-content:center;
}
section > .item {
width:calc(100%/3 - 10px);
margin:5px;
}
section > .item:nth-child(3),
section > .item:nth-child(4){
order:1;
width:calc((100%/3 - 20px) /2);
}
/* Irrelevant styles */
section > .item {
padding:10px;
box-sizing:border-box;
text-align:center;
background:#000;
color:#fff;
border-radius:10px;
}
<section>
<div class="item">box1</div>
<div class="item">box2</div>
<div class="item">box3</div>
<div class="item">box4</div>
<div class="item">box5</div>
</section>

Trying to create a row with 4 cells

I am trying to create a row with 4 cells and I don't know why its not working.
I have created a parent row and 4 children.
<div className='row'>
<div className='col-1-of-4'>
hi
</div>
<div className='col-1-of-4'>
hi
</div>
<div className='col-1-of-4'>
hi
</div>
<div className='col-1-of-4'>
hi
</div>
</div>
(Ignore the className for class, as I am using react)
and the css properties are:
[class^="col-"] {
float: left;
&:not(:last-child) {
margin-right: $gutter-horizontal;
}
}
.col-1-of-4 {
width: calc((100% - #{$gutter-horizontal}) / 4);
}
What it does is, calculates total width, and then subtracts the margin and then divides by 4.
Technically it should work and I should be able to see 4 cells in a row.
But the result I get is, 3 cells in a row and the fourth one on the next line.
the result should be something like this
hi hi hi hi
but the actual result is
hi hi hi
hi
Here is the working code
https://codepen.io/sarmad1995/pen/REYXBV?editors=1100
You shouldn't divide the margin inside your calculation. It should be outside or will you will remove less than the margin set for each element. You are setting X margin and only removing X/4 so each element will take 25% - X/4 + X (the last one 25% - X/4) as a space thus the total will be 100% + 2X which bigger than 100%.
.col-1-of-4 {
width: calc(100% / 4 - #{$gutter-horizontal});
}
.row {
max-width: 114rem;
margin: 0 auto;
}
.row:not(:last-child) {
margin-bottom: 8rem;
}
.row::after {
content: "";
display: table;
clear: both;
}
.row [class^="col-"] {
float: left;
}
.row [class^="col-"]:not(:last-child) {
margin-right: 6rem;
}
.row .col-1-of-4 {
width: calc(100% / 4 - 6rem);
background-color: red;
}
<div class='row'>
<div class='col-1-of-4'>
hi
</div>
<div class='col-1-of-4'>
hi
</div>
<div class='col-1-of-4'>
hi
</div>
<div class='col-1-of-4'>
hi
</div>
</div>
And in case you need a space between behavior (which is what you want) you can do like this:
.col-1-of-4 {
width: calc(100% / 4 - 3*#{$gutter-horizontal}/4);
}
That you can also write like this:
.col-1-of-4 {
width: calc((100% - 3*#{$gutter-horizontal})/4);
}
You need to remove the 3 margins (defined for the first 3 elements) from the total width then divide by 4:
.row {
max-width: 114rem;
margin: 0 auto;
}
.row:not(:last-child) {
margin-bottom: 8rem;
}
.row::after {
content: "";
display: table;
clear: both;
}
.row [class^="col-"] {
float: left;
}
.row [class^="col-"]:not(:last-child) {
margin-right: 6rem;
}
.row .col-1-of-4 {
width: calc(100% / 4 - 3*6rem/4);
background-color: red;
}
<div class='row'>
<div class='col-1-of-4'>
hi
</div>
<div class='col-1-of-4'>
hi
</div>
<div class='col-1-of-4'>
hi
</div>
<div class='col-1-of-4'>
hi
</div>
</div>
You should apply the same logic for all your other classes
Looking at your codepen example, you are setting a margin-right.
[class^="col-"] {
float: left;
&:not(:last-child) {
margin-right: $gutter-horizontal;
}
}
Removing this gives you the four columns as described.
Please in future include all relevant code to your question.

CSS Grid auto placement in IE/EDGE

While using the old CSS grid spec that is supported by IE 11 and EDGE. Is it possible for the grid items to be auto placed like the current spec?
i.e. to not have to define the column on a grid item:
.item:nth-child(1) {
-ms-grid-column: 1;
}
.item:nth-child(2) {
-ms-grid-column: 2;
}
.item:nth-child(n) {
-ms-grid-column: n;
}
https://codepen.io/JoeHastings/pen/mMPoqB
The answer is NO (unfortunately).
Old specs section about auto-placement has such preamble
This section describes early thinking around automatic placement of Grid Items. Multiple algorithms are possible for such a feature. One is proposed here.
Run this code in IE/Edge and you'll see a lot of rows with 1 in console because IE/Edge stacks all grid items in first cell and you can't force IE/Edge to place grid items automatically. Setting -ms-grid-column and -ms-grid-row to auto won't change anything, because this value is not supported (as you can see in MSDN links). Demo:
var gridItems = document.querySelectorAll(".grid__item");
for (var i = 0; i < gridItems.length; i++) {
var gridItem = gridItems[i];
console.log(window.getComputedStyle(gridItem)["-ms-grid-row"]);
console.log(window.getComputedStyle(gridItem)["-ms-grid-column"]);
}
.grid {
display: -ms-grid;
-ms-grid-columns: 100px 100px 100px;
-ms-grid-rows: 100px 100px 100px;
}
.grid__item {
-ms-grid-row: auto;
-ms-grid-column: auto;
background-color: tomato;
color: white;
font-size: 20px;
display: flex;
align-items: center;
justify-content: center;
}
<div class="grid">
<div class="grid__item">One</div>
<div class="grid__item">Two</div>
<div class="grid__item">Three</div>
<div class="grid__item">Four</div>
<div class="grid__item">Five</div>
<div class="grid__item">Six</div>
<div class="grid__item">Seven</div>
<div class="grid__item">Eight</div>
<div class="grid__item">Nine</div>
</div>

CSS Nth Child calculate top height based on N

I am trying to use CSS to calculate the top height to add every 5+1 elements.
The following code moves a series of absolute positioned elements to their respective places.
.screen [data-app]:nth-child(5n-4) { left:0%; }
.screen [data-app]:nth-child(5n-3) { left:20%; }
.screen [data-app]:nth-child(5n-2) { left:40%; }
.screen [data-app]:nth-child(5n-1) { left:60%; }
.screen [data-app]:nth-child(5n) { left:80%; }
This creates the illusion of five columns with absolutely positioned elements. Now what I'd like to do is for the next row of five to also have top:180px added to them, and the row after that top:360px etc.. etc..
Can this be done without the need to write CSS code for the position of every single element. Some way of applying a top attribute for each group of five based on n value of the current element.
You can either use SASS or Flexbox in order to achieve the result you're looking for. In this case SASS will create a more bloated CSS-file than ideal, but will use the rules you posit, while Flexbox will be more future-proof and easily maintained.
The HTML
<div class="screen">
<div data-app>asdf1</div>
<div data-app>asdf2</div>
<div data-app>asdf3</div>
<div data-app>asdf4</div>
<div data-app>asdf5</div>
<div data-app>asdf6</div>
<div data-app>asdf7</div>
<div data-app>asdf8</div>
<div data-app>asdf9</div>
<div data-app>asdf10</div>
<div data-app>asdf11</div>
</div>
SASS
.screen {
position: relative;
}
.screen [data-app] {
$height: 180px;
$offset: 20%;
$blocks_per_row: 5;
position: absolute;
width: 20%;
#for $i from 0 through 20 {
$y: floor($i / $blocks_per_row);
$x: $i % 5;
&:nth-child(#{$y}n+#{$i}) {
left: $x * $offset;
top: $y * $height;
}
}
}
Flexbox
.screen {
display: flex;
flex-flow: row wrap;
justify-content: flex-start;
align-content: flex-start;
align-items: flex-start;
}
.screen [data-app] {
flex: 0 1 20%;
height: 180px;
}
As you can see, there's no upper limit in the Flexbox solution and it's very clean. I hope any of these solutions help you.

Resources