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.
Related
I want to make a grid with different column sizes ('ITEM = V' covers all width 'ITEM A' or 'P' or 'T' cover each 50 percent of the grid width), as shown in the image. Any help?
i ve been tryin to solve this for a week now. Really what's wrong with this. (video should take two columns)
<div class="grid-container">
<div *ngFor="let media of allMedia">
<div *ngIf="media.type==='V'" class="item1">
{{media.title}}
</div>
<div *ngIf="media.type==='A'" >
{{media.title}}
</div>
<div *ngIf="media.type==='P'" >**Bold Text Here**
{{media.title}}
</div>
<div *ngIf="media.type==='T'">
{{media.title}}
</div>
</div>
</div>
CSS
.grid-container {
display: grid;
background-color: #2196F3;
grid-template-columns: 50% 50%;
}
.item1 {
grid-area: 2 / 1 / span 2 / span 2 !important;
border-style:solid;
text-align:center
}
It'd be best to use display: grid; for something like this.
You'd have to add unique classes/id's for the children elements and then set the grid-area property on each of them.
The layout of grid-area is:
grid-area: row-start / column-start / row-end / column end;
You can also use shorthand if two properties have the same value:
grid-area: 2 / 1
/* Equates to: */
grid-area: 2 / 1 / 2 / 1
Example:
.outer-grid {
display: grid;
height: 100vh;
}
.newspaper1 {
grid-area: 1 / 3 / 2 / 1;
border-style: solid;
}
.newspaper2 {
grid-area: 2 / 1;
border-style: solid;
}
.newspaper3 {
grid-area: 2;
border-style: solid;
}
.newspaper4 {
grid-area: 3 / 1;
border-style: solid;
}
.newspaper5 {
grid-area: 3 / 2;
border-style: solid;
}
.newspaper6 {
grid-area: 4 / 3 / 4 / 1;
border-style: solid;
}
<div class="outer-grid">
<div *ngIf="item==='V'" class="newspaper1">
some content
</div>
<div *ngIf="item==='A'" class="newspaper2">
some content
</div>
<div *ngIf="item==='P'" class="newspaper3">
some content
</div>
<div *ngIf="item==='T'" class="newspaper4">
some content
</div>
<div *ngIf="item==='A'" class="newspaper5">
some content
</div>
<div *ngIf="item==='V'" class="newspaper6">
some content
</div>
</div>
Here's a good interface for learning CSS Grid if you want to learn more: https://alialaa.github.io/css-grid-cheat-sheet/
An expanded question on :
pure CSS multiple stacked position sticky?
is there a way to calculate the top position of the followup header in order to stack the headers as per the the example. I do not know the count of the amount of headers there will be so i cannot say:
.headers {position:sticky}
.header-1 {top:0;}
.header-2 {top:1em}
.header-3 {top:2em}
.header-4 {top:3em}
but would need to calculate the difference
HTML:
<div class="container">
<div class="headers header-1">header 1<div>
<div class="content">This is the content<div>
<div class="headers header-2">header 2<div>
<div class="content">This is the content<div>
<div class="headers header-3">header 3<div>
<div class="content">This is the content<div>
<div class="headers header-4">header 4<div>
<div class="content">This is the content<div>
I would need to somehow calculate the :nth-child or :type-of or so method as the list grows. not sure if it could be done in css but would like to know if it is possible
If the question is Can I use the n of nth-child or nth-of-type to calculate attributes automatically?
The answer is No, you can't, at least for now.
But there are several workarounds:
This one is not very elegant, but it's actually the most used one so far.
.bars span {
display: block;
height: 1em;
margin-bottom: 1em;
background-color: salmon;
}
.bars span:nth-child(1) {
width: 1em;
}
.bars span:nth-child(2) {
width: 2em;
}
.bars span:nth-child(3) {
width: 3em;
}
.bars span:nth-child(4) {
width: 4em;
}
// ... and many more
<div class="bars">
<span></span>
<span></span>
<span></span>
<span></span>
</div>
And if you're using precompiled css such as scss, it can be shortened as:
#for $i from 1 through 20 {
.bars span:nth-child(#{$i}) {
width: #{$i}em;
}
}
The other one is using css variable. But you have to assign the variables manually:
.bars span {
display: block;
height: 1em;
margin-bottom: 1em;
background-color: salmon;
}
.bars span {
width: calc(var(--length) * 1em);
}
<div class="bars">
<span style="--length: 1;"></span>
<span style="--length: 2;"></span>
<span style="--length: 3;"></span>
<span style="--length: 4;"></span>
</div>
I have a dataset, and I need to print data onto these cards (one row of data per card):
magnatag.com
I am having a real hard time with the formatting. The printer they are being printed on can print all the way to .2 from the edge of 8.5 x 11 paper like this. The users want to print that far to the left and right, but the rows have to stay within card boundaries obviously.
The cards being used are all white, and one of the data points is a color the card will be printed in. To keep the example easier/cleaner than the real life problem, assume this markup:
<body>
<div class="cardSheet">
<div class="card blue">Content</div>
<div class="card red">Content</div>
<div class="card green">Content</div>
<div class="card green">Content</div>
<div class="card red">Content</div>
<div class="card blue">Content</div>
<div class="card green">Content</div>
<div class="card red">Content</div>
<div class="card green">Content</div>
<div class="card green">Content</div>
</div>
</body>
After the fifth row, the next row will print on the second page, etc.
There is a good bit of formatting within an individual card, but I think I can handle that. Getting 5 printable boxes per page that will print onto these cards (with .21" left and right margins in print preview, top/bottom per the card)
If varying browsers adds complexity, assume Google Chrome v 53.x
Thanks in advance for any help!
You will need to put this on a page by itself to test it. I did a few runs but I dont have any letter size pager here only a4 to test. It looks like it will work though. I used chrome and set margins to none in the print options.
I only did a quick run to show one page but you can easily add a page break after the 5th card to go to the next page. If you dont know how to do that then I can help out later with that.
Hope this helps and if you need help understanding something leave a comment.
printBlock("blue");
printBlock("red");
printBlock("green");
printBlock("green");
printBlock("red");
function printBlock(color) {
var block = "<div class='card " + color + "'>CONTENT<div>";
$(".page").append(block);
}
* {
margin: 0px;
padding: 0px;
}
body {
margin: 0;
padding: 0;
}
* {
box-sizing: border-box;
-moz-box-sizing: border-box;
}
.page {
width: 215.9mm;
min-height: 279.4mm;
margin: 1cm auto;
position: relative;
padding-left: 6.35mm;
padding-top: 19.05mm;
outline: 1px solid cyan;
}
.card {
position: relative;
width: 203.2mm;
height: 50.8mm;
background-color: #FFF;
float: left;
outline: 1px dashed #000;
padding-left: 20px;
padding-right: 20px;
padding-top: 15px;
}
.blue {
background-color: #DBFFFF;
}
.red {
background-color: #FFDBDB;
}
.green {
background-color: #EDFFDB;
}
#page {
size: 215.9mm 279.4mm;
margin: 0;
}
#media print {
.page {
margin: 0;
border: initial;
width: 215.9mm;
min-height: initial;
box-shadow: initial;
background: initial;
outline: none;
}
.card {
outline: none;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<div class="page"></div>
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.
Below I am using an extraction from a 12-grid 960px system.
<style>
body {
background: gray;
}
#container_12 {
width: 960px;
margin-left: auto;
margin-right: auto;
background: white;
overflow: hidden;
}
.column_1, .column_2, .column_3, .column_4, .column_5, .column_6, .column_7, .column_8, .column_9, .column_10, .column_11, .column_12 {
float : left;
margin-left : 10px;
margin-right : 10px;
margin-bottom: 10px;
}
.column_1 {
width : 60px;
}
.column_2 {
width : 140px;
}
.column_3 {
width : 220px;
}
.column_4 {
width : 300px;
}
.column_5 {
width : 380px;
}
.column_6 {
width : 460px;
}
.column_7 {
width : 540px;
}
.column_8 {
width : 620px;
}
.column_9 {
width : 700px;
}
.column_10 {
width : 780px;
}
.column_11 {
width : 860px;
}
.column_12 {
width : 940px;
}
</style>
<body>
<div id="container_12">
<!-- First row -->
<div class="column_1" style="height: 400px; background: red;">
</div>
<div class="column_11" style="height: 200px; background: red;">
</div>
<!-- Second row -->
<!--
This column overlaps into second row
<div class="column_1">
</div>
-->
<div class="column_5" style="height: 200px; background: green;">
</div>
<div class="column_3" style="height: 200px; background: green;">
</div>
<div class="column_3" style="height: 200px; background: green;">
</div>
</div>
</body>
The output:
http://jsfiddle.net/hnDtY/
Now let's say if I copy the two rows above to have a total of 4 rows. But I want to give the first two rows a purple background and the last two rows a white background:
http://jsfiddle.net/QZuED/
The problem with what I did above is I had to create a new div called "row" and wrap it around the two columns. This makes it inconsistent from the rest of the layout which does not have a div "row" wrapping every row. If I added a div "row" on each row and gave it a overflow: hidden property, then it will be impossible to have one column span two rows, because it would push the items in the second row down. So how do grid systems handle this situation?
Indeed, nesting the blocks inside of a div would force them to be unable to extend into the rest of the content. The answer I find most commonly used is a repeating background image instead.
body {
background: gray url(web.png) repeat-x;
}
This would also allow you to use a gradient that fades into the rest of the background. Here's your jsfiddle tweaked to reflect this.