icons, which are equally distributed across the grid - css

Is it possible to equally distribute the icons using only CSS?
I want to get this result (I have not reputation to post images)
http://i.stack.imgur.com/bC0Aw.jpg
I found a solution using javascript:
_http://jsfiddle.net/VLr45/59
I tried flexbox, but got this
http://jsfiddle.net/egns7cj1/
http://jsfiddle.net/egns7cj1/2/
http://i.stack.imgur.com/h8tU2.jpg

Wrap the items inside another parent which would have flex-basis: 33%. Change the value based on the screen size using media queries.
.flex-container {
flex-flow: row wrap;
display: flex;
width: 100%;
height: 320px;
border: 1px #eee solid;
background: #ffd54f;
}
.inner-container {
display: flex;
flex: 0 0 33%;
justify-content: center;
}
.item {
flex: 0 1 auto;
width: 100px;
height: 100px;
background: #fff;
border: 1px #777 solid;
}
#media (min-width: 991px) {
.inner-container {
flex: 0 0 25%;
}
}
#media (min-width: 1200px) {
.inner-container {
flex: 0 0 20%;
}
}
<div class="flex-container">
<div class="inner-container">
<div class="item"></div>
</div>
<div class="inner-container">
<div class="item"></div>
</div>
<div class="inner-container">
<div class="item"></div>
</div>
<div class="inner-container">
<div class="item"></div>
</div>
<div class="inner-container">
<div class="item"></div>
</div>
<div class="inner-container">
<div class="item"></div>
</div>
<div class="inner-container">
<div class="item"></div>
</div>
<div class="inner-container">
<div class="item"></div>
</div>
</div>

Related

Making a container fit the width of its children

I'm trying to dynamically size a container to the width of its children when they're broken down into columns and rows. This can easily be achieved by writing a bunch of media queries and hard coding the width of the container, but I'm looking for a way to do it dynamically with CSS.
In this example id like .container to only be a multiple of the width of a fixed size .item (200px, 410px, 620px, 830px, etc) and not include the empty space to the right.
.container {
background-color: #555;
display: flex;
flex-wrap: wrap;
gap: 10px;
max-width: 1000px;
padding: 10px;
}
.item {
aspect-ratio: 1;
background-color: #ddd;
width: 200px;
}
<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>
If the width of items are fixed you can try like below:
.wrapper {
display: grid;
grid-template-columns: repeat(auto-fill,200px); /* same as width of items */
gap: 10px;
padding: 10px; /* move the padding here */
}
.container {
grid-column: 1/-1; /* take all the columns */
background-color: #555;
outline: 10px solid #555; /* use outline to cover the padding */
display: flex;
flex-wrap: wrap;
gap: inherit;
}
.item {
aspect-ratio: 1;
background-color: #ddd;
width: 200px;
}
<div class="wrapper">
<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>
</div>

How to have make a div take a minumum of 50% space but if no sibling is present take 100%

Simply put I have:
#Container {
display:'flex';
flex-wrap:'wrap';
}
.item {
flex-basis: '50%'
}
Scenario one:
<div id=Container>
<div class="item"></div> 33 %
<div class="item"></div> 33 %
<div class="item"></div> 33%
</div>
Scenario 2
<div id=Container>
<div class="item"></div> 50 %
<div class="item"></div> 50 %
</div>
scenario 3:
<div id=Container>
<div class="item"></div> 100 %
</div>
What I want in general tems is this to be fluid, the more items I put in the less space each item will have but if there is only 1 then I want it to take full space.
First you have to add display: flex; to #Container
#Container{
display: flex;
}
If you want to equally distribute the space between children then you can use flex property as
.item{
flex: 1;
}
Above CSS is minimum required styles, rest is for demo
#Container {
display: flex;
margin-top: 1rem;
}
.item {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
padding: 1rem;
}
.item:nth-child(1) {
background-color: red;
}
.item:nth-child(2) {
background-color: blueviolet;
}
.item:nth-child(3) {
background-color: aquamarine;
}
<div id="Container">
<div class="item">33 %</div>
<div class="item">33 %</div>
<div class="item">33 %</div>
</div>
<div id=Container>
<div class="item"> 50 % </div>
<div class="item"> 50 % </div>
</div>
<div id=Container>
<div class="item">100 %</div>
</div>
I think that this example could give you an idea of how to achieve what you want:
https://codepen.io/Eylen/pen/vYJBpMQ
.Container {
display: flex;
flex-wrap: wrap;
margin-bottom: 8px;
}
.item {
flex-grow: 1;
margin: 0 12px;
background: #f1f1f1;
}
Your main issue in the code that you gave, is that you're missing the flex item behaviour. I have just set that the item can grow to fill the space with the flex-grow:1.
You can make sure a flex child covers up the space if it can, you can provide flex-grow: 1
#Container {
display:flex;
}
.item {
width: 100%;
flex-grow: 1;
border: 1px solid;
text-align: center;
}
<h1> Scenario 1 </h1>
<div id=Container>
<div class="item">33 %</div>
<div class="item">33 %</div>
<div class="item">33%</div>
</div>
<h1> Scenario 2 </h1>
<div id=Container>
<div class="item">50 %</div>
<div class="item">50 %</div>
</div>
<h1> Scenario 3 </h1>
<div id=Container>
<div class="item">100 %</div>
</div>
Added a demo below.
$( document ).ready(function() {
$( "#add" ).click(function() {
$('#container').append('<div class="item"></div>');
});
$( "#remove" ).click(function() {
$('#container').children().last().remove();
});
});
#container {
width:100%;
height:500px;
background-color:#ebebeb;
display:flex;
flex-direction: column;
}
.item {
width:100%;
display: flex;
flex: 1;
border-bottom:1px solid #007cbe;
}
.item1 {
background:#007cbe;
}
.item2 {
background: #d60000;
}
.item3 {
background: #938412
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
<div class="item item1">1</div>
<div class="item item2">2</div>
<div class="item item3">3</div>
</div>
<button id="add"> Add </div>
<button id="remove"> Remove </div>
Apply to the below CSS to fulfill your requirement.
#Container {
display: flex;
}
.item {
width: 100%;
min-height: 100px;
border: 1px solid;
}

Display list of elements as table with CSS only?

Display list as a table with 3 columns, with the items evenly spread, and having 10px margin from every sides and between rows.
.item { width: 10px; height: 10px; background: black; }
.grid { background: #eee; }
<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>
Should be rendered as
It is possible to achieve that with flex layout, but it would require more complicated HTML, see example below.
.item { width: 10px; height: 10px; background: black; }
.grid { background: #eee; padding: 10px 10px 0 10px; }
.row { display: flex; justify-content: space-between; padding: 0 0 10px 0; }
<div class="grid">
<div class="row">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<div class="row">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</div>
I wonder if it would be possible to do with pure CSS, without adding any additional HTML elements. The size of .items shouldn't be changed, and it's unknown.
You can do this with flexbox by adding a hidden element between the first and last row that will be width:100% thus you will avoid changing the html:
.item {
width: 10px;
height: 10px;
background: black;
}
.row {
display: flex;
justify-content: space-between;
padding: 10px;
background: #eee;
flex-wrap: wrap;
}
.row:after {
content: "";
width: 100%;
height: 10px;
}
.row :nth-child(n + 4) {
order: 1;
}
<div class="row">
<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>
If the number of element is unknown you can consider CSS grid:
.item {
width: 10px;
height: 10px;
background: black;
}
.row {
display: grid;
grid-template-columns: repeat(3,1fr);
grid-gap: 10px;
padding:10px;
background: #eee;
}
.row :nth-child(3n + 2) {
margin:auto;
}
.row :nth-child(3n + 3) {
margin-left:auto;
}
<div class="row">
<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>
Temani Afif has written a good answer. The flexbox one will work only for 2 to 3 rows but the grid version will work for more items.
The grid CSS can be simplified further by using space-between, thus getting rid of margins and n-th child selectors.
.item {
width: 10px;
height: 10px;
background: black;
}
.row {
display: grid;
grid-template-columns: repeat(3,10px); /*change this*/
grid-gap: 10px;
padding:10px;
background: #eee;
justify-content: space-between; /*add this*/
}
<div class="row">
<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>

Maintain ratio of container and children while resize

I have modular grid of cards with and without image, based on flexbox.
Normally cards without image are 50% of the width, cards with image are 100% of the width, and those cards without image that doesn't have a pair are also 100%.
----------------
[[ txt ][ img ]] – card with an image
----------------
[ txt ][ txt ] – 2 cards without image
----------------
[ txt ] – card without image
----------------
[[ txt ][ img ]] – card with an image
----------------
Is it possible to maintain ratio of the cards and its content while resize, and also maintain modularity with css?
Here's the code
that let me maintain ratio, but when I try to apply this technique to cards children everything breakes
<div class="wrapper">
<div class="card">
<div class="card-text">
</div>
<div class="card-image">
</div>
</div>
</div>
.wrapper
display: flex
flex-wrap: wrap
justify-content: space-between
width: 620px
.card
height: 0
padding-bottom: 50%
display: flex
flex-direction: row
justify-content: space-between
flex: 1 1 300px
.has-card-image .card-text,
.has-card-image .card-image
height: 300px
width: 300px
I can see one way this could be done w/o script.
Either as in this case, using px values, or e.g. using vw, and the reason is that the card-text and card-image needs to know the wrapper's width to be able to size according to the expected output (which mean percent can't be used).
Fiddle demo
Stack snippet
.wrapper {
display: flex;
flex-wrap: wrap;
width: 600px;
}
.card {
display: flex;
flex: 1 300px;
}
.card .card-text,
.card .card-image {
height: 100px;
width: 300px;
}
.card .card-text:only-child {
flex: 1 300px;
}
/* demo styles */
.card .card-text, .card .card-image {
border: 1px solid;
box-sizing: border-box;
}
.card .card-text::before {
content: 'text';
}
.card .card-image::before {
content: 'image';
}
<div class="wrapper">
<div class="card">
<div class="card-text">
</div>
<div class="card-image">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
<div class="card-image">
</div>
</div>
</div>
If you need the margin, you'll need an extra wrapper
Fiddle demo
Stack snippet
.wrapper {
width: 620px;
overflow: hidden;
}
.inner {
display: flex;
flex-wrap: wrap;
margin-left: -20px;
}
.card {
display: flex;
flex: 1 300px;
}
.card .card-text,
.card .card-image {
height: 100px;
width: 300px;
margin-left: 20px;
}
.card .card-text:only-child {
flex: 1 300px;
}
/* demo styles */
.card .card-text,
.card .card-image {
border: 1px solid;
box-sizing: border-box;
}
.card .card-text::before {
content: 'text';
}
.card .card-image::before {
content: 'image';
}
<div class="wrapper">
<div class="inner">
<div class="card">
<div class="card-text">
</div>
<div class="card-image">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
<div class="card-image">
</div>
</div>
</div>
</div>
Updated
Here is a version using vw and margin, and is responsive.
Note, the make up for margin set on the wrapper can also be set on each item, though I found it simpler like this.
Fiddle demo
Stack snippet
.wrapper {
width: calc(80vw + 20px); /* 20px extra for margin */
margin: 0 auto;
overflow: hidden;
}
.inner {
display: flex;
flex-wrap: wrap;
margin-left: -20px;
}
.card {
display: flex;
flex: 1 40vw;
}
.card .card-text,
.card .card-image {
height: 100px;
width: 40vw;
margin-left: 20px;
}
.card .card-text:only-child {
flex: 1 40vw;
}
/* demo styles */
.card .card-text,
.card .card-image {
border: 1px solid;
box-sizing: border-box;
}
.card .card-text::before {
content: 'text';
}
.card .card-image::before {
content: 'image';
}
<div class="wrapper">
<div class="inner">
<div class="card">
<div class="card-text">
</div>
<div class="card-image">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
</div>
<div class="card">
<div class="card-text">
</div>
<div class="card-image">
</div>
</div>
</div>
</div>

Flexbox grid last row wrong margins between items

I'm still experimenting with flexbox, but there's this case I can't solve.
I have this grid
<div class="wrapper">
<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>
</div>
With the following CSS:
.wrapper{
width:100%;
oveflow:hidden;
margin: 0;
padding:0;
}
.container {
width:100%;
display: flex;
flex: 1;
flex-flow: row wrap;
justify-content: space-between;
margin: 0;
}
.container .item {
display: block;
margin: 0 0 30px;
width: 29.666%;
}
But when I use this, items in the last row are rendered with a different "space between" them than the items in the previous row.
Look at this picture. This is what I get:
Trying to fix this, the only thing I can find is to set items' lateral margin as auto, like this
.container .item {
display: block;
margin: 0 auto 30px;
width: 29.666%;
}
But now, I have lateral margins between the items and the container border, like this:
Why does this happen?
Is there a way to solve this other than having negative lateral margins on the container div?
I didn't see the same result you did, but your margins looks a bit weird. I stripped it down to this:
.wrapper {
background: blue;
}
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin: 0;
}
.item {
background: yellow;
height: 30px;
width: 29.666%;
}
.item:not(:nth-last-child(-n+3)) {
margin-bottom: 30px;
}
<div class="wrapper">
<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>
</div>
I see no defaults.
I did modify a bit your css code given so things can be seen and margin set only from second line:
.wrapper {
}
.container {
width: 100%;
background: #3197D3;
display: flex;
flex-flow: row wrap;
justify-content: space-between;
margin: 0;
}
.container .item {
display: block;
width: 29.666%;
min-height: 100px;
background: #FFFF4D;
}
.item:nth-child(3) ~.item {
margin-top: 30px;
}
/* demo purpose*/
.container:before {
content:'.'attr(class);
width:100%;/* will span whole line */
padding:0.15em;
font-size:3em;
text-align:center;
color:white;
background:rgba(255,255,255,0.5);
}
.container .item {
display: flex;
}
.item:before {
content: attr(class);
margin: auto;
color:#3197D3;
font-size:2em;
}
<div class="wrapper">
<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>
</div>

Resources