For the following the anchor text isn't centered. If I change the anchor's display from flex to block then the text is centered. Why is this?
Ive only tested on Chrome so far.
<ul>
<li>Link</li>
<li>Link</li>
<li>Link</li>
<li>Link</li>
<li>Link</li>
<li>Link</li>
</ul>
*, *:before, *:after {
-moz-box-sizing: border-box;
-webkit- box-sizing: border-box; box-sizing: border-box;
}
ul {
display: flex;
flex-flow: row wrap;
padding: 0;
width: 40%;
margin: auto;
border: 1px solid gold;
}
li {
list-style-type: none;
}
a {
background: grey;
width: 200px;
border: 1px solid red;
text-align: center;
display: flex;
}
http://codepen.io/anon/pen/dgmbH
Note: Before you go ahead to read my answer, I would like you to
notify that am not using any of the PROPRIETARY PREFIXES, if it
doesn't work for you, its time to update your browser, or try adding
the prefixes like -moz or -webkit and see if it works for you.
The correct way to do is to use display: flex; for the ul element and flex-grow on li elements...
ul {
display: flex;
padding: 0;
width: 40%;
margin: auto;
border: 1px solid gold;
}
li {
list-style-type: none;
flex-grow: 1;
}
Demo
You are using a fixed width on a tag i.e width: 200px; and that kills the idea of flex layout, so take that out, and alter your CSS with the one provided by me.
Here, I've used flex-grow with a value of 1 so that each of the li element shares the equal amount of width
If you are looking to wrap the cells if they exceed the containers width, than you need to use the following properties on ul element like
ul {
display: flex;
padding: 0;
width: 40%;
margin: auto;
border: 1px solid gold;
flex-direction: row;
flex-flow: row wrap;
}
Demo (Resize your window to see the effect)
Sample 1, the wrapped element will stretch to full width
Sample 2, Elements wrapped equally further
Also note that am using min-width: 100px; on li elements to force wrap in the demonstration
As you commented that you wanted three li on each row, than instead of using flex-grow: 1; you need to use flex: 1 1 33%; like
li {
list-style-type: none;
flex-grow: 1;
min-width: 100px;
flex: 1 1 33.33%;
}
Demo
Sample 3, Equal number of li on each row
Sample 4, Equal number of li on each row even when resized
On further resize, they will accommodate automatically say two in a row and one in a row..
Related
I would like to have an element that grow and reduce to the dimension of its content only with css rules.
Here an example:
ul {
list-style: none;
padding: 1rem 1rem 1rem 0;
background-color: lightblue;
max-height: 300px;
display: inline-flex;
flex-flow: column wrap;
align-items: flex-start;
width: 238px;
}
ul li {
width: 100px;
border: 1px solid red;
margin-left: 1rem;
}
/* HTML */
<ul>
<li>item</li> // repeated n times
</ul>
https://codepen.io/mt_dt/pen/GRJYaNj?editors=1100
It should be something like that:
https://ibb.co/6wmYkGX
If you want to have each element on the list to be as wider as the ul element, you need to remove hardcoded height and flex properties (they have no use) from the ul element and set width: 100%; on the lis:
ul {
list-style: none;
padding: 1rem 1rem 1rem 0;
background-color: lightblue;
width: 235px;
}
ul li {
width: 100%;
border: 1px solid red;
margin-left: 1rem;
}
Have a look to this codepen. Hope it helps!
When using input and button elements inside a flex container, the flex and/or flex-grow properties don't seem to do anything.
Code that demonstrates my issue.
button,
input {
font-size: 1rem;
}
button {
border: none;
background-color: #333;
color: #EEE;
}
input {
border: 1px solid #AAA;
padding-left: 0.5rem;
}
.inputrow {
width: 30rem;
display: flex;
margin: 0 -.25rem;
}
.inputrow>* {
margin: 0 .25rem;
border-radius: 2px;
height: 1.75rem;
box-sizing: border-box;
}
.nickname {
flex: 1;
}
.message {
flex: 4;
}
.s-button {
flex: 1;
}
<div class="inputrow">
<input type="text" class="nickname" placeholder="Nickname">
<input type="text" class="message" placeholder="Message">
<button type="submit" class="s-button">Submit</button>
</div>
Code that shows what I'm expecting. (using DIVs instead of input and button).
.inputrow {
width: 30rem;
display: flex;
flex-flow: row nowrap;
margin: 0 -.25rem;
}
.inputrow>* {
margin: 0 .25rem;
height: 1.75rem;
}
.nickname {
flex: 1;
background-color: blue;
}
.message {
flex: 4;
background-color: red;
}
.s-button {
flex: 1;
background-color: green;
}
<div class="inputrow">
<div class="nickname">Nickname</div>
<div class="message">Message</div>
<div class="s-button">Submit</div>
</div>
An input element, unlike a div, comes with a default width.
Here's a simple illustration of this setting:
The browser automatically gives the input a width.
input {
border: 1px solid blue;
display: inline;
}
div {
border: 1px solid red;
display: inline;
}
<form>
<input>
<br><br>
<div></div>
</form>
Also, an initial setting on flex items is min-width: auto. This means that items cannot shrink below their width on the main axis.
Hence, input elements cannot shrink below their default width and may be forced to overflow the flex container.
You can override this behavior by setting your inputs to min-width: 0 (revised codepen)
Here's a full explanation: Why don't flex items shrink past content size?
In some cases, you may need to override input widths using width: 100% or width: 0.
I needed to wrap the input element with a styled element and than set the input width and min-width as below:
.field__input input {
width: 0;
min-width: 100%;
}
If you have an input element inside a flex box, you can define width: 0 and still can utilize flex: 1 or whatever value you need.
This is Christof Kälin's answer in the comments for another answer. Putting it here for visibility.
const
setValue = (btn, amount) => {
const input = btn.closest('.stepper').querySelector('.stepper-val');
input.value = +input.value + amount;
},
handleDecr = e => setValue(e.target, -1),
handleIncr = e => setValue(e.target, 1);
document.querySelectorAll('.stepper').forEach(s => {
s.querySelector('.stepper-minus').addEventListener('click', handleDecr);
s.querySelector('.stepper-plus').addEventListener('click', handleIncr);
});
html {
font-family: Arial, Helvetica, sans-serif;
/* font-size: 3vw; */
}
html, body, div, button, input {
box-sizing: border-box;
}
#atf {
height: 100vh;
/* flex-container */
display: flex;
justify-content: center;
align-items: center;
}
.stepper {
/* flex-container */
display: flex;
/* formatting */
width: 12rem;
height: 2rem;
}
.stepper-minus {
/* flex-item */
flex-grow: 1;
/* flex-container */
display: flex;
justify-content: center;
align-items: center;
/* formatting */
background-color: deepskyblue;
border: 1px solid lightgray;
border-radius: .6rem 0 0 .6rem;
cursor: pointer;
}
.stepper-val {
/* flex-item */
flex-grow: 2;
/* flex-container */
text-align: center;
/* formatting */
border-top: 1px solid lightgray;
border-bottom: 1px solid lightgray;
border-left: none;
border-right: none;
width: 0;
}
.stepper-plus {
/* flex-item */
flex-grow: 1;
/* flex-container */
display: flex;
justify-content: center;
align-items: center;
/* formatting */
background-color: deepskyblue;
border: 1px solid lightgray;
border-radius: 0 .6rem .6rem 0;
cursor: pointer;
}
.stepper>button:hover {
background-color: blue;
}
<div id="atf">
<div class="stepper">
<button class="stepper-minus">−</button>
<input class="stepper-val" type="text" name="val" value="32">
<button class="stepper-plus">+</button>
</div>
</div>
Edit: Making this answer a community wiki so that I don't get unearned credit.
I would like to extend #Michael Benjamin solution
In some cases, you may need to override input widths using width: 100% or width: 0.
you can also do calc(100%)
if the parent is a flexible container set with the usual flex: 1 (flex-grow: 1) and you want the input to shrink with the parent, this is what has worked for me:
width: 35px;
flex: 1 2 0px;
Give this as a class to the input, this will make it take the whole space when its available, but shrink to minimum size when resized.
Edit:
This works because it's a shorthand for flex: <flex-grow> <flex-shrink> <flex-basis> as explained here https://css-tricks.com/snippets/css/a-guide-to-flexbox/#flex
The '2' is assigned to flex-shrink which makes the element shrink.
Sometimes you still need to add min-width: 0; as mentioned in other comments to remove the min-width defined by browsers (for small containers)
Use flex-basis: 0; for input or input container solves the problem.
I'd recommend setting the width to 100% or what ever percentage you want but you should set it. That works for me.
I have an ul container and li menu items. Container is 100% width and li items are 50% width of the parent element. Parent is set to display flex and flex direction is column. Now the items are half the width of the flex parents but when I set the child items to flex-grow: 1 nothing seems to be happening at all.
menu-secondary-container ul {
display: flex;
flex-direction: column;
}
#menu-secondary li {
box-sizing: border-box;
font-size: 13px;
border: 1px solid white;
line-height: 2.3;
width: 50% !important;
padding: 0;
flex-grow: 1;
}
I want two items to be in one row and total of two rows.
As I commented above you need to fix your code like this in order to have 2 items per row:
ul {
display: flex;
flex-wrap: wrap;
margin: 0;
padding: 0;
list-style: none;
}
ul li {
box-sizing: border-box;
font-size: 13px;
border: 1px solid #000;
line-height: 2.3;
flex: 0 1 50%; /* Or flex-basis:50% Or width:50% */
padding: 0;
}
<ul>
<li>aaaa</li>
<li>bbb</li>
<li>cccc</li>
<li>ddd</li>
</ul>
I have a simple Flexbox footer. When the screen gets below 580px, the layout changes as you can see below.
I have two primary issues:
The justify-content property on the <ul> doesn't seem to kick in. If I've made the <ul> a display: flex item, surely the child elements should be flex items, no? On the mobile version of the footer, the <li> items stay stuck to the right-hand side.
Why is the right-hand side container (that switches to being the bottom item on the mobile view) so much bigger in height than its sibling at the mobile size? There is no extra padding or height value added to this item.
** Note - I've put a 1px border around every element to make it easier to see what is going on.
* {
border: 1px solid black;
}
body {
margin: 0;
padding: 0;
}
footer {
width: 100%;
display: flex;
justify-content: space-between;
background: red;
box-sizing: border-box;
padding: 1rem;
}
.footer-inner {
background: blue;
width: 30%;
display: flex;
align-items: center;
padding: 1rem;
color: white;
}
#footerright {
display: flex;
justify-content: flex-end;
}
#footerright ul {
display: flex;
list-style-type: none;
justify-content: flex-end;
}
#footerright ul li {
padding: 0px 10px;
color: white;
}
#media screen and (max-width: 580px) {
footer {
flex-direction: column;
align-items: center;
}
.footer-inner {
justify-content: center;
min-width: 240px;
}
#footerright {
justify-content: center;
}
#footerright ul {
justify-content: center;
}
}
<footer>
<div class="footer-inner" id="footerleft">©<span id="footer-year">Year</span> The Company</div>
<div class="footer-inner" id="footerright">
<ul>
<li id="facebook">Twi</li>
<li id="instagram">Fac</li>
<li id="twitter">Ins</li>
</ul>
</div>
</footer>
View on CodePen
Why is the righthand side container so much bigger in height than its
sibling at the mobile size?.
Because when in non-mobile size, the default value of flex row items's align-items kicks in, which is stretch, and make items on the same row equally high, which is not the case when wrapped, or using flex column direction, where they instead collapse to their own height, based on margin, border, padding and content.
In this case, if you remove the preset padding/margin from the ul, it will collapse to the li's size, where they appear to have an equal height, though based on e.g. different font size, etc., they might become unequal again.
Flexbox “Justify Content” not working
The margin/padding reset (ul {margin: 0; padding: 0;}) will also take care of the small left offset the ul suffer from, in both mobile and non-mobile view, though in mobile view it is more obvious, which I also guess is what you meant with justify-content doesn't seem to kick in.
Concerning the "right-alignment" in mobile view: Add padding-left: 0; to the ul to avoid the default padding of uls which causes a horizontal offset from the centered position.
And concerning the size of the second container: Add padding: 0 to .footer-inner and margin: 0 to #footerright ul to reset the default paddings and margins:
https://codepen.io/anon/pen/GOQwBV
You can solve your problem by adding the basic CSS browser reset (equal height problem) and replacing the justify-content: center property inside the #footerright > ul to align-items: center
* {
margin: 0;
padding: 0;
box-sizing: border-box;
border: 1px solid black;
}
html, body {
width: 100%;
}
footer {
width: 100%;
display: flex;
justify-content: space-between;
background: red;
box-sizing: border-box;
padding: 1rem;
}
.footer-inner {
background: blue;
width: 30%;
display: flex;
align-items: center;
padding: 1rem;
color: white;
}
#footerright {
display: flex;
justify-content: flex-end;
}
#footerright ul {
display: flex;
list-style-type: none;
justify-content: flex-end;
}
#footerright ul li {
padding: 0px 10px;
color: white;
}
#media screen and (max-width: 580px) {
footer {
flex-direction: column;
align-items: center;
}
.footer-inner {
justify-content: center;
min-width: 240px;
}
#footerright {
justify-content: center;
}
#footerright > ul {
/*justify-content: center;*/
align-items: center; /* because of the changed direction this is now horizontal alignment / centering */
}
}
<footer>
<div class="footer-inner" id="footerleft">©<span id="footer-year">Year</span> The Company</div>
<div class="footer-inner" id="footerright">
<ul>
<li id="facebook">Twi</li>
<li id="instagram">Fac</li>
<li id="twitter">Ins</li>
</ul>
</div>
</footer>
Certain browsers have default "User Agent Stylesheets", that are the default styles applied to elements on the page. In Webkit, the browser adds a few properties to your ul that are affecting your styles:
-webkit-margin-before: 1em;
-webkit-margin-after: 1em;
-webkit-padding-start: 40px;
As you can see, there are margins being added before and after your ul, causing the mobile issue you described, where the ul is taller than its sibling. There is also padding, which is shifting your contents to the right.
To reset these styles, you just need to set those defaults to zero like so:
#footerright ul {
-webkit-margin-before: 0;
-webkit-margin-after: 0;
-webkit-padding-start: 0;
padding-left: 0;
margin-top: 0;
margin-bottom: 0;
}
Note: you don't need to reset the -webkit- rules above, you'd also be fine just resetting the padding-left, margin-top, and margin-bottom.
When specifying column-count of 2:
.parent {
-webkit-column-count: 2;
overflow-y: scroll;
max-width: 100%;
height: 400px;
}
.child {
display: block;
}
I get way more than 2 columns if there is a height specified. It grows horizontally instead of vertically, overflowing the max-width rather than overflowing the height.
JSFiddle example: http://jsfiddle.net/brentonstrine/6bk5jb3L/2/
I would like to have it scroll vertically rather than horizontally, and stay limited to the column-count which I have specified.
I can't add extra markup, I have to work with the existing elements.
You can also achieve this with flexbox. Remember to use the proper css prefixes.
My solution is here on JSFiddle:http://jsfiddle.net/6bk5jb3L/41/
I also remove the -webkit-column-count style.
Below will get rid of the scroll bar for you:
.parent::-webkit-scrollbar {
display: none;
}
EDIT
Here is an example of the fix that keeps the -webkit-column-count style: http://jsfiddle.net/6bk5jb3L/47/
.parent {
overflow-x: auto;
width: 100%;
height: 400px;
border: solid 1px red;
box-sizing: border-box;
display:flex;
flex-direction: row;
flex-wrap: wrap;
column-count: 2;
}
.parent::-webkit-scrollbar {
display: none;
}
.child {
display: block;
width: 50%;
border: solid 1px blue;
box-sizing: border-box;
height: 40px;
}
Since you cannot change the markup, add this JQuery that will wrap your parent <div> with another <div> like this: http://jsfiddle.net/6bk5jb3L/12/
JQuery
$( ".parent" ).wrap( "<div class='parentToTheParent'></div>" );
CSS
.parentToTheParent {
overflow-y: scroll;
max-width: 100%;
height: 400px;
border: solid 1px red;
}
.parent{ width: 100%; -webkit-column-count: 2;}
.child{
border: solid 1px blue;
}
PS the parent to the parent was just for fun, don't over think it lol