Add a margin to li using flexbox - html

I am using flexbox to layout my things. I have 5 lis (so far, but that will change), with the following width: flex-basis:calc(100%/3). So there will be 3 li's in each row. The wrapper (ul) has a width of 70%.
So far so good. The problem is, when I add a margin to the li's. When I add a margin to the li's, there will only be 2 li's in each row with some extra space, but I need 3.
So I found 2 solutions that give me other problems:
One solution would be to add the margin to the li's, let's say 10px. Then subtract 20px (10 * 2) from the width and height of each li's. I can't do that, because I need the li's to be the size I set, and not smaller.
Another solution would be to set justify-content to either space-around or space-between. The problem with that is that I need the lis to be in columns and rows, (like a chart). And if I change justify-content, the li's wouldn't be in a chart like order.
Is there a way to add a margin to the li without affecting any other property's?
(I'm open to JavaScript/JQuery if that's the only choice.)
JSFiddle
Here's a code snippet:
body, html {
height:100%; margin: 0; padding:0;
}
#flexWrapper {
display: flex;
justify-content: center;
height: 100%;
align-items: center;
overflow: auto;
}
#flexContainer {
width: 70%;
background-color:yellow;
list-style-type: none;
padding: 0;
margin: auto;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
align-items: center;
align-content:flex-start;
}
li {
background-color: tomato; border: 1px solid black; height:50px;
box-sizing: border-box;
flex-basis:calc(100%/3);
margin:10px;
}
<div id="flexWrapper">
<ul id="flexContainer">
<li class="flex-item">1</li>
<li class="flex-item">2</li>
<li class="flex-item">3</li>
<li class="flex-item">4</li>
<li class="flex-item">5</li>
</ul>
</div>

Ok, so I finally got an answer that works! I have to give partial credit to #Syahrul for starting up the idea (in the comments).
So basically what I'll be doing is this. If we want to add 1.5% of a margin, we'll add (1.5 * 2) * 3 (1.5 * 2 because the margin is on both sides of every li. * 3 because we have 3li'sin every row.) to thewidthof the wrapper ('#flexContainer), so we have 79% of a width for #flexContainer.
Next, we'll subtract 3% (margin size (1.5 * 2)) from the width of the li. And that's flex-basis:calc(100%/3 - 3%).
And there you have it! Here's the updated JSFiddle
body, html {
height:100%; margin: 0; padding:0;
}
#flexWrapper {
display: flex;
justify-content: center;
height: 100%;
align-items: center;
overflow: auto;
}
#flexContainer {
width: 79%;
background-color:yellow;
list-style-type: none;
padding: 0;
margin: auto;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
align-items: center;
align-content:flex-start;
}
li {
background-color: tomato; border: 1px solid black; height:100px;
box-sizing: border-box;
flex-basis:calc(100%/3 - 3%);
margin:1.5%;
}
<div id="flexWrapper">
<ul id="flexContainer">
<li class="flex-item">1</li>
<li class="flex-item">2</li>
<li class="flex-item">3</li>
<li class="flex-item">4</li>
<li class="flex-item">5</li>
</ul>
</div>

Related

How can I make the space between the items of the nav bar be the same between each other

I'm trying to make the space between the items of the navbar be the same between each other. Sounds like something simple but I haven't managed to do it. I would really appreciate some help with this. Here's the HTML and the CSS. Here's the relevant code:Here's a photo of the output
HTML:
<nav class="menu">
<ul>
<li>Home</li>
<li><a href="tweets.html">Why programming? <a></li>
<li><a href="goals.html">Aspirations and goals<a></li>
<li>Projects</li>
<li>Favourite books</li>
<li>Interests</li>
</ul>
</nav>
CSS:
nav{
width: 100%;
display: flex;
flex-flow: row wrap;
justify-content: space-between;
right: -90px;
flex-wrap: wrap;
bottom:10px;
align-items:flex-end;
font-size: 20 px;
padding: 0px;
line-height: 0px;
padding-left:50px;
padding-right: 50px;}
Can't exactly test it with just the code provided but try setting your margins in css, they should control your distance. You may want to tinker with margin-left and margin-right
justify-content: space-evenly; /* Distribute items evenly Items have equal space around them */ May also be worth a try
You can use flex box on ul as:
ul {
display: flex;
list-style-type: none;
justify-content: space-between;
}
ul {
display: flex;
list-style-type: none;
justify-content: space-between;
}
<nav class="menu">
<ul>
<li>Home</li>
<li>Why programming? </li>
<li>Aspirations and goals</li>
<li>Projects</li>
<li>Favourite books</li>
<li>Interests</li>
</ul>
</nav>
To fix your problem after I tested it with the code above and fixed it just by adding a few things. This works with your existing css code still being used!!
You not using the li or ul class in your css which is a big part of what your trying to do. You can add li a to have padding-left: 4px; and padding-right: 4px; and display: flex; - Also by making ul list-style-type: none; than your list won't have a list icon next to it.
ul {
list-style-type: none;
}
li {
float: left;
}
li a {
display: flex;
padding-left: 4px;
padding-right: 4px;
}
Do this
ul {
display: flex;
justify-content : space-between or space-evenly (as per design)
width:100%
}
As because you are using flex-box, so you can use justify content space between, space around or space evenly, or you can use margin left, right property
ul {
display: flex;
justify-content : space-between / space-evenly / space-around
}

html css full width, images only, resizable horizontal menu

I' trying to make a horizontal menu with special conditions
these are the rules I have to stick with:
html + css
menu should resize to the width of the container (100% of container).
so the wider the container the bigger (height, width) the menu
menu elements are images with different width
every image(menu element) is close to the next and previous (no gaps in between)
all dimensions should be expressed in % (no fixed size)
the code:
<div id="menu-container">
<ul>
<li><img src="myImg01"></li>
<li><img src="myImg02"></li>
<li><img src="myImg03"></li>
</ul>
</div>
css
#menu-container{
width:100%;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
display: table;
}
li {
display: table-cell;
}
li img{
width:100%;
}
this works in firefox and safari
does not in chrome and similar... (it seems like all images are scaled in different %)
I've searched and did not found a similar issue
could you help please?
Will try to clarify.
I need that all images retain their aspect ratio even after scaling
you should add max-width in your div , and make display flex wrap
hay I hope this example will be helpful, so try like this:
CSS
#menu-container{
width:100%;
border: 1px solid red;
}
ul {
margin: 0;
padding: 0;
display: flex;
align-items: center;
flex-wrap: nowrap;
list-style-type: none;
}
li {
width: 10%;
height: 0;
padding-bottom: 10%;
background-repeat: no-repeat;
/*background-size: contain;*/
background-size: cover;
background-position: center center;
}
li a {
display: block;
width: 100%;
height: 0;
padding-bottom: 100%;
}
HTML
<div id="menu-container">
<ul>
<li style="background-image: url(https://static.scientificamerican.com/sciam/cache/file/4E0744CD-793A-4EF8-B550B54F7F2C4406_source.jpg);">
</li>
<li style="background-image: url(https://www.afd.fr/sites/afd/files/styles/visuel_principal/public/2019-01-07-16-19/mangrove%20couv.jpg);">
</li>
<li style="background-image: url(https://blog.nationalgeographic.org/wp-content/uploads/2020/05/May-11_Dorset-heathland_shutterstock_1332881306_sml-1140x450.jpg);">
</li>
</ul>
</div>
You can CSS grid.
#menu-container {
width:100%;
}
ul.menu {
display: grid;
grid-template-columns: 1fr 25% 2fr; // You can use percentages or the fr unit It represents a fraction of the available space in the grid container (works like Flexbox’s unitless values).
list-style-type: none;
margin: 0;
padding: 0;
}

css grid stretch row contents to fit parent container

Is there a way to get grid items to stretch the length of the parent container? I cannot for the life of me figure it out.
basically im trying to build a calendar with grid because idk it seemed like the best option. ive got the 7 columns and they stretch the width of the parent container. however, the grid rows do not. i've tried loads of potential solutions from SO and other places but none of them seem to work.
setting days height:100%; causes it to stretch too far down the page and overflow, which is undesirable. if i take that out, then they don't fill in the space and just bunch up. ideally I would like 7 x 5 with square boxes, but at this point i'll take evenly spaced rectangles. what am I doing wrong or misunderstanding?
here's a snippet: (css is scss)
.main-container {
display: flex;
width: 100%;
height: 100%;
}
.calendar {
background-color: transparent;
width: 100%;
height: 100%;
//remove italics is for testing. delete after done
font-style: normal;
position: relative;
}
.month {
padding: 7rem 10rem;
width: 100%;
background: #eee;
text-align: center;
}
.month ul {
display: flex;
justify-content: space-between;
list-style: none;
& a{
color: #222;
text-decoration: none;
}
}
// use grid 7 x 5 (modify for february in js)
.weekdays {
background: #222;
color: #eee
display: grid;
grid-template-columns: repeat(7,1fr);
list-style: none;
text-align: center;
font-weight: bold;
}
.days {
list-style: none;
text-align: center;
font-weight: 200;
text-decoration: none;
background: #eee;
display: grid;
grid-template: repeat(5,1fr) / repeat(7,1fr); // rows / columns
justify-content: stretch;
width: 100%;
height: 100%;
position: absolute;
& > li {
background: #www;
height: 100%;
}
}
<div class="main-container">
<div class="calendar">
<div class="month">
<ul>
<li class="prev">&#10094</li>
<li>August<br><span style="font-size:18px">2020</span></li>
<li class="next">&#10095</li>
</ul>
</div>
<ul class="weekdays">
<li>Monday</li>
<li>Tuesday</li>
<li>Wednesday</li>
<li>Thursday</li>
<li>Friday</li>
<li>Saturday</li>
<li>Sunday</li>
</ul>
<ul class="days">
<li>1</li>
<li>2</li>
<li> 3</li>
<li> 4</li>
...
<!--and so on-->
logic is: wrap all the grid containers in a flex item because flex is the "layout" and grid is the organisation.
I figured out a solution that worked. I added a display:flex and set it to column in a parent element but I forgot where because I was just trial and erroring a lot of things. I think it was the calendar element since that's not in the OP. it gave me this output which is what I was looking for (sorry for the colours).

How to align one item on viewport center using flexbox or grid? [duplicate]

This question already has answers here:
Align 3 unequal blocks left, center and right
(4 answers)
Closed 3 years ago.
I am creating simple navigation with flexbox CSS3 and I have a list with 3 items but those items have not specified width. Now I want to have the middle item to be placed in the center of the viewport. When I have that kind of situation my middle li is not centered on the viewport. Is there any way to center one item and other elements to be relative to this item?
See the differences between first and second navigation. On second navigation when there is one item it's properly centered to the viewport. I want to center the first one like second. Li element with class middle must be at the center of the viewport.
EDIT
Some of the answers did the typical moving first and last LI to the edges of the UL LIST. That's not the point, MIDDLE li must be at the center of the viewport and first and last LI should have only paddings and width: initial
ANSWER
I cannot add answer here so I paste 'codepen' link with answer which I want to get
https://codepen.io/freestyle09/pen/xxxvwPm
UPDATED CODE
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
nav {
border: 1px solid red;
display: flex;
justify-content: center;
}
ul {
display: flex;
justify-content: center;
list-style: none;
border: 1px solid green;
width: 1200px;
}
ul > li {
padding: 20px;
white-space: nowrap;
border: 1px solid blue;
}
li:not(.middle) {
flex-basis: 0%;
flex-grow: 1;
}
nav .test {
display: flex;
justify-content: center;
width: 800px;
border: 2px solid pink;
padding: 20px
}
<nav>
<ul>
<li><span>Lorem ipsum sit</span></li>
<li><span>Lorem ipsum sit</span></li>
<li class='middle'><span>Vey long string, very very very long string</span></li>
<li><span>About</span></li>
<li><span>About</span></li>
</ul>
</nav>
<nav>
<div class='test'>
<p>Vey long string, very very very long string</p>
</div>
</nav>
I'm not entirely sure I understand what you're trying to accomplish but this sounds like maybe what you're after?
Addendum, you just described the purpose of a table for tabular data. Hope this helps, cheers!
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
nav {
border: 1px solid red;
}
ul {
display: table;
width: 100%;
list-style: none;
align-items: center;
border: orange 3px dashed;
}
ul > li {
display: table-cell;
text-align: center;
padding: 20px;
border: green 1px dotted;
}
ul > li:nth-child(odd) {
width: 20%;
}
<nav>
<ul>
<li>Lorem ipsum sit</li>
<li class='middle'>Vey long string, very very very long string</li>
<li>About</li>
</ul>
</nav>
<nav>
<ul>
<li>Vey long string, very very very long string</li>
</ul>
</nav>
On way to approach this is to give the li.middle element a higher flex-grow priority and a lower flex-shrink priority than the other li elements.
The style flex is a shorthand for:
flex-grow
flex-shrink
flex-basis
It will take flex values such as these:
flex: 1 1 20%; // flex-grow priority of 1, flex-shrink priority of 1, pre-flex starting width of 20%
flex: 2 0 60%; // flex-grow priority of 2, will never shrink, pre-flex starting width of 60%
Using these two values above we can declare that:
one class of element has a default width of 20% and can both grow and shrink to fill the width available
another class of element has a default width of 60%, is twice as likely to grow wider than the other elements, but can never shrink to less than 60%
Working Example:
nav {
border: 1px solid red;
}
ul {
display: flex;
list-style: none;
justify-content: center;
border: 1px solid green;
margin-left: 0;
padding-left: 0;
}
ul > li {
padding: 20px;
}
li {
border: 1px solid blue;
}
li {
flex: 1 1 20%;
}
li.middle {
flex: 2 0 60%;
text-align: center;
}
<nav>
<ul>
<li>Lorem ipsum sit</li>
<li class="middle">Very long string, very very very long string</li>
<li>About</li>
</ul>
</nav>
<nav>
<ul>
<li class="middle">Very long string, very very very long string</li>
</ul>
</nav>
Adding the following properties to your style should fix your problem.
ul > li {
padding: 20px;
flex: 1;
text-align: center;
}
That will set all the li element sizes to be equal and align their text to the center of it.

Adapt all childs width with parent width

I have an html page structure like this:
<div id="list">
<ul>
<li style="background-color:orange;">Lorem</li>
<li style="background-color:red;">Lorem</li>
.............
<li style="background-color:black;">Lorem</li>
<li style="background-color:blue;">Lorem</li>
</ul>
</div>
On this page, I want all list element to have the same width - I don't care about the content, only the color is really important in this case - and I want all thos elements to fit in their parent div (#list) when the page just loaded, this mean no scroll.
And this list is not final, I can add or delete somme elements in my list after the page load. I would like to know if there is a CSS way to get this result, JavaScript is not really suitable in this case.
Is that possible ?
You can achieve this kind of behavior by using flex:
HTML structure:
<div id="list">
<ul>
<li style="background-color:orange;">Lorem</li>
<li style="background-color:black;">Lorem</li>
...
<li style="background-color:blue;">Lorem</li>
</ul>
</div>
CSS:
#list {
border-style: solid;
border-width: 3px;
white-space: nowrap;
}
#list ul {
display: flex;
flex-direction: row;
margin: 5px;
padding: 0;
}
#list ul li {
border-style: solid;
height: 50px;
list-style-type: none;
}
Here is a working demo: http://jsfiddle.net/kmbxawdd/1/
Yes, you can use flexible boxes:
#list {
display: flex; /* Magic begins */
border: 3px solid;
padding: 1em;
}
#list > li {
width: 0; /* Ignore the width of the content */
flex-grow: 1; /* Distribute remaining space equally */
overflow: hidden; /* Hide possible overflow */
height: 50px;
border-style: solid;
}
<ul id="list">
<li style="background-color:orange;">Lorem</li>
<li style="background-color:red;">Lorem</li>
<li style="background-color:black;">Lorem</li>
<li style="background-color:blue;">Lorem</li>
</ul>
JSFiddle Example
Flexbox is your friend.
div#list {
height: 800px; /*Whatever you want, really*/
width: 800px; /*Again, substitute this with whatever size you like*/
}
div#list ul {
height: 100%;
width: 100%;
display: flex;
flex-flow: row nowrap;
align-content: stretch;
list-style: none;
padding: 0;
margin: 0;
}
div#list ul li {
-webkit-flex: 0 1 100%;
flex: 0 1 100%;
}
You can try to set display to "table" on list and "table-cell" on li. But it will work as you expect only if all li elements will contain content with same width. And list itself must have explicitly defined width, of course.