How do dynamically position and size div elements? - html

I am trying to have an angular component that can dynamically position and resize div elements depending on how many div elements are to be displayed. This is what I have achieved so far.
EDIT: If you checkout my stackblitz example I am using display: flex
(thus flexbox). The issue I am having is how can I make sure that a
row will at most only have 3 divs and then wrap to the next line and
that the divs length will always be the same?
.
EDIT 2: My goal is that when there is one or two divs the length of
the div is half that of the container. That is why I put a 'ruler' at
the top in the image below. If there are more than 2 divs the length
of the divs should be 1/3 of the length of the container. And a row
should be filled by three divs before wrapping to the next row.
Below is a visual representation of what I am trying to achieve:
All the divs in a particular set are of the same width and height.
I see how I can hack around by using calc() in width but then I will have to pass the number of divs variable to my css file. Also I am aware that using Multiple conditions in ngClass - Angular 4 is an option, but I would like to use that if I did not have any other option.
How can I achieve what I am trying to achieve with css only (if possible)? If it is not possible to use css only I will gladly take any other recommendation.

First make flex container with
.container1 {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
}
Second use calc() to specify items width
.item {
width: calc(33.33% - 0px);
}
Third specify first and second child behavior. They should grow, but max-width: 50%
.item:first-child, .item:nth-child(2) {
flex-grow: 1;
max-width: 50%;
}
.container1 {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
outline: dashed red 1px;
margin: 10px 0
}
.item {
height: 100px;
background-color: green;
outline: 1px dashed blue;
width: calc(33.33% - 0px);
}
.item:first-child, .item:nth-child(2) {
flex-grow: 1;
max-width: 50%;
}
<div class="container1">
<div class="item"></div>
</div>
<div class="container1">
<div class="item"></div>
<div class="item"></div>
</div>
<div class="container1">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<div class="container1">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<div class="container1">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<div class="container1">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<div class="container1">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<div class="container1">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>

Checkout sample working copy Check the flex will slove the above issues i guess.
.parent {
display:flex;
justify-content:space-around;
flex-wrap:wrap;
}
.option-box{
width:40%;
border: 1px blue solid;
margin: 3px
}
#media screen and (max-width: 600px) and (min-width: 301px) {
.option-box {
width:30%;
}
}
#media screen and (max-width: 300px) {
.option-box {
width:100%;
}
}

Related

How to create a CSS GRID with 3 distinct head elements

I get a list using the CSS display: grid as shown below
My task has to be edited so that the list will look like this when it is displayed on PC, while on my mobile it will look like the first image.
The first 3 elements will be larger than the rest.
And responsive support
Here is my code:
HTML:
.grid {
width: 638px;
display: grid;
grid-row-gap: 68px;
grid-column-gap: 12px;
grid-template-rows: auto auto;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
justify-content: space-between;
}
.item {
border: 3px solid green;
width: auto;
height: 150px;
}
<div class="grid">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
I tried to fix it but it doesn't work like, thanks everyone!
you may rethink it from a 12 columns grid and reset grid-column spanning to the item.
possible example
.grid {
width: 638px;
display: grid;
grid-row-gap: 68px;
grid-column-gap: 12px;
grid-template-rows: auto auto;
grid-template-columns: repeat(auto-fit, minmax(35px, 1fr));/* 35 x 4 = 140 */
justify-content: space-between;
}
.item {
border: 3px solid #4285F4;
border-radius:3px;
width: auto;
height: 150px;
grid-column:auto / span 4; /* about 35px X 4 of width */
margin-right:8px;
}
.item:nth-child(3), .item:nth-child(3)~.item {
margin-right:0;
}
.item:nth-child(3)~.item {
grid-column:auto / span 3;
}
<div class="grid">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
spanning columns rules and grid-template-columns can be reset via the mediaquerie your want to use.
You have to use a number that contains 3 and 4 as multiplicator. For example 12. So You divide the grid into 12 columns. Then you use nth-child pseudo selctor to selct the first 3 and give them a span of 4 and every other child a span of 3.
with :nth-child(-n+3) you select the first 3 elements. As you want them to be 3 boxes in one row the need to span 4 to fit the 12 columns.
with :nth-child(n+3) you select all element with exeption of the first 3. Now you need to let them span 3 columns to fit 4 boxes within the 12 column wide row.
.grid {
width: 638px;
display: grid;
grid-row-gap: 68px;
grid-column-gap: 12px;
grid-template-rows: auto;
grid-template-columns: repeat(12, 1fr);
}
.item {
border: 3px solid green;
height: 150px;
}
.item:nth-child(n+3) {
grid-column: span 3;
}
.item:nth-child(-n+3) {
grid-column: span 4;
}
<div class="grid">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>

Flexbox items with min width and adaptive to content

I want to make flexbox with responsive to content items.
Here is example code:
HTML:
.container {
width: 200px;
height: 400px;
display: flex;
flex-flow: row wrap;
}
.item {
flex-basis: 40px;
background-color: orange;
margin: 0 10px 10px 0;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item">this is text content and again and again this is text content and again and again</div>
</div>
And this is what I want to achieve:
How can I achieve that behavior? Thanks!)
If you want your page to be responsive to different resolution then u shouldn't adopt the habit of defining height and width in terms of px.
instead try to put width and height interms of % , width defined in % tend to adjust with resolution but width defined in terms of px tend to remain static and insensitive to changing resolution.
try this instead,
.container {
width: 800px;
height: 400px;
display: flex;
flex-flow: row wrap;
}
.item {
flex-basis: 25%;
background-color: orange;
margin: 0 10px 10px 0;
height: 50%;
}
.items {
flex-basis: 51%;
background-color: orange;
margin: 0 10px 10px 0;
height: 50%;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="items">this is text content and again and again this is text content and again and again</div>
<div class="item"></div>
</div>
This Works fine. All the best
Any reason you have a strong attachment to flexbox? This would be super easy using the bootstrap grid. (I see you have the container class, so you likely already have bootstrap installed)
<div class="container">
<div class="item col-md-3"></div>
<div class="item col-md-3 col-md-offset-1"></div>
<div class="item col-md-3 col-md-offset-1"></div>
<div class="item col-md-3"></div>
<div class="item col-md-3 col-md-offset-1"></div>
<div class="item col-md-3 col-md-offset-1"></div>
<div class="item col-md-6">this is text content and again and again this is text content and again and again</div>
<div class="item col-md-3 col-md-offset-1"></div>
</div>
If you're not into using bootstrap, CSS3 now has a native grid layout which should also suit your purpose.
In your situation, I think this would be the way to go. Flexbox is a great layout, but it's meant more for dynamic displays where you don't need precise control over the size/dimension of the items.
You can add a class, let's say extra.
And add assign property of max-width:max-content; to it.
.container {
display: flex;
width: 300px;
height: 300px;
flex-wrap: wrap;
border: 2px solid red;
}
.item {
flex: 1;
min-width: calc(100px - 10px);
max-width: calc(100px - 10px);
height: calc(100px - 10px);
margin: 5px;
background: green;
}
.extra {
max-width: max-content !important;
max-width: -moz-fit-content !important;
color: white;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item extra">this is extra text and expands</div>
<div class="item"></div>
</div>

Responsive Layout with same growing gaps in each row

I have a container with a random number of elements which should always align on the left side. The container width can increase or decrease.
If the container size is increasing then the first element from the row+1 should go one row back and should appear on the right side. But it should only go one row back if it can fit there with a padding on the left and right side.
While the element does not have space one row abouve, then the space between the elements should grow until the element from row+1 can fit in this row.
The same functionality should work also in the reverse way.
Here is my code:
.container {
min-height: 400px;
display: flex;
flex-wrap: wrap;
flex-direction: row;
justify-content: space-around;
align-items: center;
align-content: flex-start;
}
.container:after {
display: block;
content: " invisible node ";
flex(999 999 auto);
}
.item {
flex: 0 0 auto;
margin: 5px;
width: 50px;
height: 50px;
background-color: green;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
https://jsfiddle.net/p6k537ep/
My Problem ist that in the second row the space between the elements is not the same as in the first row (It depends how many elements are there).
Edit:
But it is working that the elements from the second row can only move one row abouve if they have anough space. The Gap is growing in the correct way in the first row but not in the second one.
AFAIK, this is not solvable in Flexbox without adding invisible non-semantic helper elements to hold the horizontal rhythm of the last row (with the same width and horizontal margins as .items, but zero height).
However, this is easily solvable in CSS Grid, which seems perfect for this:
.container {
min-height: 400px;
display: grid;
grid-template-columns: repeat(auto-fill, 60px);
justify-content: space-around;
align-items: center;
align-content: start;
}
.item {
flex: 0 0 auto;
margin: 5px;
width: 50px;
height: 50px;
background-color: green;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
and kind of solvable with inline-blocks, using the similar pseudo-element hack and some "magic" of the inline formatting:
.container {
min-height: 400px;
text-align: justify;
font-size: 5px;
line-height: 0;
}
.container:after {
display: inline; /* it's important, it should continue the same line! */
/* each character below acts as an invisible placeholder for the item */
/* with em dashes, they would be 1em (5px here) wide each */
content: '— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — ';
letter-spacing: 55px; /* expand each placeholder to the item width */
word-spacing: -56px; /* collapse the whitespaces */
margin-left: 5px;
}
.item {
display: inline-block;
margin: 5px;
width: 50px;
height: 50px;
background-color: green;
vertical-align: top;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
But, honestly, I'd not recommend using the second option in production. Left-aligning the items instead would probably be a better fallback for browsers that don't support Grid.
You could use the margin property on the :after pseudoelement to keep the blocks together.
fiddle
.container {
min-height: 400px;
display: flex;
flex-wrap: wrap;
flex-direction: row;
justify-content: space-between;
align-items: center;
align-content: flex-start;
}
.container:after {
display: block;
content: " ";
margin-left: auto; /* added */
}
.item {
flex: 0 0 auto;
margin: 5px;
width: 50px;
height: 50px;
background-color: green;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>

Aligning gallery with the rest of the content

I'm having a problem with the gallery alignment with the rest of the content.
I'm using container with padding that I'm getting through gutters and the gallery is with the padding of the span, plus the padding of the gutters.
I want to make them aligned.
Image that shows the alignment
HTML:
<header id="header">
<div class="container">
header
</div>
</header>
<div id="content">
<div class="gallery">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</div>
<div id="sidebar">sidebar</div>
CSS:
#import "susy";
$susy: (
columns: 12,
gutter-position: inside,
global-box-sizing: border-box
);
#mixin container-padding($padding: gutter()) {
padding: 0 $padding 0 $padding;
}
$gallery_layout: (
columns: 12,
gutters: 1/10,
gutter-position: split
);
#include border-box-sizing;
.container {
#include container;
#include container-padding;
}
.gallery {
> .item {
#include with-layout($gallery_layout) {
height: 250px;
margin-bottom: gutter() * 2;
background-color: brown;
#include span(2);
}
}
}
#header {
height: 80px;
background-color: blue;
}
#content {
#include span(9);
background-color: yellow;
}
#sidebar {
#include span(3);
background-color: red;
height: 515px;
}
Note; The margin-bottom: gutter() * 2; is due the gutters split.
Example running here.
#EDIT
It works doing this:
$gallery_layout: (
columns: 12,
gutters: 1/10,
gutter-position: after
);
The only problem though is that it leaves an empty space on the end and don't fill the entire div. - Example here.
Try using the gallery mixin: #include gallery(2);
Here's the updated pen

CSS - How to stack divs by columns of 2

I have a variable number of divs, which should be displayed on two lines, as follows
[1] [3] [5] [7]
[2] [4] [6] ...
I looked at the column-count property, however it's not exactly what I need, as it fixes the number of columns, whereas in my case it should be dynamic. (what I need would be a similar line-count property, which doesn't seeem to exist).
Is there a pure CSS solution, or should I make container divs for every groups of 2 vertical divs?
Thanks,
Edit :
Here is a simplified code of my case. Actually, As I set the height property on my container div, shouldn't the article divs be stacked by at most 2 ? Now they're overflowing the container.
<html>
<head>
<link rel="stylesheet" type="text/css" href="test.css">
</head>
<body>
<div class="container">
<div class="article">A</div>
<div class="article">B</div>
<div class="article">C</div>
<div class="article">D</div>
<div class="article">E</div>
</div>
</body>
</html>
and the CSS
.article {
width:50px;
height:50px;
border:1px gray dashed;
margin:1px;
}
.container {
height:110px;
max-height:110px;
}
However with this code all the article divs are in one column.
You can use the columns css property on a container:
#columns-holder {
-moz-columns: 100px;
-webkit-columns: 100px;
columns: 100px;
-moz-column-gap: 15px;
-webkit-column-gap: 15px;
column-gap: 15px;
}
.box {
width: 100px;
height: 100px;
margin-bottom: 15px;
background: grey;
-webkit-column-break-inside: avoid;
page-break-inside: avoid;
break-inside: avoid;
}
<div id="columns-holder">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
<div class="box">7</div>
<div class="box">8</div>
<div class="box">9</div>
<div class="box">10</div>
</div>
You can do this using flexbox and flex-direction: column;
Doing so will allow you to have new columns once the bottom of parent element is reached.
Here is an example:
*
{
box-sizing: border-box
}
.flex-parent
{
display: flex;
flex-flow: column wrap;
/* this indicates, when a new "column" will be started */
height: 200px;
align-content: flex-start;
}
.flex-parent .col
{
flex: 0 0 auto;
width: 100px;
height: 50px;
background-color: silver;
margin: 4px;
}
<div class="flex-parent">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
<div class="col">4</div>
<div class="col">5</div>
<div class="col">6</div>
<div class="col">7</div>
<div class="col">8</div>
<div class="col">10</div>
<div class="col">11</div>
<div class="col">12</div>
</div>
When I have to do something like this i use float property with a code like this to be applied to each div you want to display:
.divclass{
float: left;
margin: 10px;
width: 300px;
}
don't forget to clear float after the list of divs:
<br stytle="clear: both;">
With this structure I get to put as many divs as they can fit on the screen width and to put the others on a new line. Obviously the number of divs on each row will be dependent on the screen width or container div width.
Can help you a bit more if you provide more code of yours.
For Column-count
With a simple list mark up
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
<ul>
Use this CSS:
ul {
-moz-column-count: 2;
-moz-column-gap: 20px;
-webkit-column-count: 2;
-webkit-column-gap: 20px;
column-count: 2;
column-gap: 20px;
}
Another option is CSS3 as below:
CSS3 solution would look like this:
HTML
<div id="wrap">
<div class="list_item">A</div>
<div class="list_item">B</div>
<div class="list_item">C</div>
<div class="list_item">D</div>
<div class="list_item">E</div>
<div class="list_item">F</div>
<div class="list_item">G</div>
<div class="list_item">H</div>
</div>
CSS:
.list_item {
float: left;
margin: 5px;
padding: 5px;
width: 200px;
border: 1px solid gray;
}
#wrap {
width:460px;
column-count:2;
column-gap:20px;
-moz-column-count:2;
-moz-column-gap:20px;
-webkit-column-count:2;
-webkit-column-gap:20px;
}
you can see more details at here
Here is an example of a grid where the elements will be 4 elements on each row.
You can adjust the size of the .container element to what you want. If you don't want to support vw units.
Why widht:22%;?
The logical way would be to set width:25% right if we want 4 elements? 4x25=100.
Try to edit the code below to that :)
As you see it will wrap to a new line.
Setting it slightly less 23% or 22% I went with 22%.
Now you have some space for border margins and paddings.
If you want them to fit perfectly next to one an other.
set the box-sizing: borderbox. and 0 margin 0 padding (and no white space)
and a width of 25%. Should get you close to a perfect fit.
.container {
width: 50vw;
border: 5px solid pink;
}
.container .item {
display: inline-block;
border: 2px solid firebrick;
width: 22%;
height: 50px;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>