Vertically aligning flex 1 content - html

I have a list where one of the items breaks onto two lines.
I need to keep all <li> elements the same height, but also center align them, which I can't seem to do (code on CodePen):
#test ul{
display:flex;
border:1px solid black;
list-style: none;
padding-left:0;
}
#test li{
flex: 1;
width:33.333333%;
border-left:1px solid black;
padding:10px;
}
<div id="test">
<ul>
<li>
Two line Text<br/>
Two line Text
</li>
<li>
One line Text
</li>
<li>
One line Text
</li>
</ul>
</div>
How can I do what I'm trying to without using any hacky paddings, margins, or heights on the "One line Text" elements? If I use the suggested align-items: center on the ul, then the borders no longer look correct, as the element is no longer full height.

align-items defaults to stretch, which make the li fill the height of the ul.
Change it to center, by adding align-items: center; to the #test ul rule, will align them vertically centered (this will make the li collapse to their content though)
#test ul {
display:flex;
align-items: center; /* added */
border:1px solid black;
list-style: none;
padding-left:0;
}
#test li {
flex: 1;
width:33.333333%;
border-left:1px solid black;
padding:10px;
}
<div id="test">
<ul>
<li>
Two line Text<br/>
Two line Text
</li>
<li>
One line Text
</li>
<li>
One line Text
</li>
</ul>
</div>
Or make the li a flex container and vertical align the a using justify-content: center, which btw defaults to flex-start.
Why the use of column direction and justify-content, because there is 2 items and you most likely want to stack them on top of each other.
#test ul{
display:flex;
border:1px solid black;
list-style: none;
padding-left:0;
}
#test li{
flex: 1;
width:33.333333%;
border-left:1px solid black;
padding:10px;
display:flex; /* added */
flex-direction: column; /* added */
justify-content: center; /* added */
}
<div id="test">
<ul>
<li>
Two line Text
Two line Text
</li>
<li>
One line Text
</li>
<li>
One line Text
</li>
</ul>
</div>
If there is only 1 item with two lines of text, we can use the default row direction and align-items
#test ul{
display:flex;
border:1px solid black;
list-style: none;
padding-left:0;
}
#test li{
flex: 1;
width:33.333333%;
border-left:1px solid black;
padding:10px;
display:flex; /* added */
align-items: center; /* added */
}
<div id="test">
<ul>
<li>
Two line Text<br>Two line Text
</li>
<li>
One line Text
</li>
<li>
One line Text
</li>
</ul>
</div>

You need to change the HTML structure a little bit & apply align-items: stretch to ul.
#test ul {
display: flex;
align-items: stretch;
}
And inside li create a .inner div and give it display: flex with align-items: center.
#test li {
flex: 1;
display: flex;
align-items: center;
}
Have a look at the working snippet below:
#test ul{
display: flex;
align-items: stretch;
border: 1px solid black;
list-style: none;
padding-left: 0;
}
#test li {
flex: 1;
display: flex;
align-items: center;
border-left: 1px solid black;
}
#test li:first-child {
border-left: none;
}
#test li .inner {
padding: 10px;
}
<div id="test">
<ul>
<li>
<div class="inner">
Two line Text<br/>
Two line Text
</div>
</li>
<li>
<div class="inner">
One line Text
</div>
</li>
<li>
<div class="inner">
One line Text
</div>
</li>
</ul>
</div>
Hope this helps!

Related

css - how to position <li> in horizontal <ul>?

I have section, which contains horizontal ul, which contains four li's,
as following:
#header-strip ul {
display: flex;
justify-content: space-between;
margin: 0;
padding: 0;
height: 4vh;
width: 100%;
background-color: grey;
list-style-type: none;
}
#header-strip li {
display: inline;
}
<section id="header-strip">
<ul>
<li>meant to be left</li
><li>meant to be centered</li
><li>meant to be just before last</li
><li>meant to be right</li
>
</ul>
</section>
Requirements:
- first item at left with some small percentage offset of screen edge
- second item centered in the middle
- third item to be at right, with some percentage space between to fourth
- fourth item at right, with percentage offset from screen edge
I am able to position li's with basic justify-content: space-between;, but don't know how to position it the custom way.
It should look like this:
Simply change the margin of the second element and make it auto
As a side note: with flexbox you don't need to worry about whitespace and no need to define element as inline
#header-strip ul {
display: flex;
margin: 0;
padding: 0;
color:#ffff;
width: 100%;
background-color: grey;
list-style-type: none;
}
#header-strip li {
margin:0 2%;
}
#header-strip li:nth-child(2) {
margin: auto;
}
<section id="header-strip">
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
</section>
if you are using flexbox:
<section id="header-strip">
<ul>
<li>meant to be left</li
><li class="fill">meant to be centered</li
><li>meant to be just before last</li
><li>meant to be right</li
>
</ul>
</section>
//css
.fill {
flex-grow: 2;
}

HTML justify content and span

.d1 {
background-color: red;
display: flex;
justify-content: center;
}
.s1 {
color: blue;
}
<div class="d1">
<u>list:</u>
<br>item1
<br>item2
<br><span class="s1">item3</span>
</div>
I am trying to make a div where its contents are aligned in the center. I use the above code to display the text list: item1 item2 item3 one below the other, list: underlined and the item3 to have blue color but this gives so strange results:
item1 and item2 but item3 is... on top and next to list:... What's the matter and how can I fix this? Ty
You can fix this by not using flex but inline-block and a wrapper <div> instead.
.d1 {
background-color: red;
text-align: center;
}
.d2 {
display: inline-block;
text-align: left;
}
.s1 {
color: blue;
}
<div class="d1">
<div class="d2">
<u>list:</u>
<br>item1
<br>item2
<br><span class="s1">item3</span>
</div>
</div>
You can use <li> along with <u> and add u li {list-style-type: none;} to disable list item circle.
Check this :
.d1 {
background-color: red;
display: flex;
justify-content: center;
}
.s1 {
color: blue;
}
u li {list-style-type: none;}
<div class="d1">
<u>list:
<li>item1</li>
<li>item2</li>
<li><span class="s1">item3</span></li>
</u>
</div>
You could make you usage of an unsorted list like this one here:
If you need a more specific solution let me know that!
.d1 {
background-color: red;
justify-content: center;
display: block;
text-align: center
}
.s1 {
color: blue;
}
<div class="d1">
<p>Items:</p>
<lu>
<li>item1</li>
<li>item2</li>
<li><span class="s1">item3</span></li>
</lu>
</div>
.d1 {
background-color: red;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.s1 {
color: blue;
}
<div class="d1">
<u>list:</u>
<br>item1
<br>item2
<br><span class="s1">item3</span>
</div>
Result okay?
why you used <u> tag and "display:flex". If you use display:flex then its child nodes will take the whole height and <u>list:</u>, <span class="s1">item3</span> have done that and created 3 column. besides other content are not considered as the child nodes.
You can see the link to clear the idea of flex

Vertical align CSS content icon with wrapped text

I need to reformat predefined HTML to give me a different layout using CSS. The HTML is returned from the server as an error message and as such I'm unable to change the format.
.server-errors ul {
list-style: none;
}
.server-errors li:before {
content: "D";
font-family: "pictos";
}
<div class="server-errors">
<ul>
<li>
<label>Server error message goes here.</label>
</li>
</ul>
</div>
The requirement is to display this with removing the <li> dot and replacing it with another (pictos) character which is left and vertically aligned.
I have managed to display the character but am unable to align it vertically as a separate entity.
I need:
---------------------------------------
- Long error message goes -
- X here and it will span -
- three lines -
---------------------------------------
I get:
---------------------------------------
- X Long error message goes here and -
- will span three lines -
- -
---------------------------------------
I'm not sure what exactly I should be changing or even which part of the CSS to look at to get the effect.
You can use css3 flexbox.
.server-errors li {
align-items: center;
display: flex;
}
Output Image:
.server-errors ul {
border: 1px solid black;
list-style: none;
padding: 10px;
width: 150px;
}
.server-errors li {
align-items: center;
display: flex;
}
.server-errors li:before {
margin-right: 10px;
content: "D";
font-family: "pictos";
}
<div class="server-errors">
<ul>
<li>
<label>Long error message goes -
- X here and it will span -
- three lines</label>
</li>
</ul>
</div>
You can either use flexbox:
.server-errors li {
display: flex;
align-items: center;
}
Or, css table-cell with more browser support:
.server-errors li:before,
.server-errors li label {
display: table-cell;
vertical-align: middle;
}
.all {
width: 300px;
display:flex;
}
li {
list-style: none;
}
.side {
width: 10px;
}
.letter {
width: 100px;
display:flex;
justify-content:center;
align-items:center;
}
.all * {
line-height: 30px;
}
.message {
display: flex;
justify-content: center;
align-items: center;
}
<body>
<div class="server-errors">
<ul>
<li>
<div class="all">
<div class="side">
<span>-</span>
<span>-</span>
<span>-</span>
</div>
<div class="letter">
X
</div>
<div>
Long error message goes here and it will span three lines
</div>
<div class="side">
<span>-</span>
<span>-</span>
<span>-</span>
</div>
</div>
</li>
</ul>
</div>
</body>

how to properly align list items vertically?

I wanted to create a list of items by displaying a name, a list of properties and an image. Although this seems like quite a common and easy problem, I am struggling to get it right.
After having changed the markup a dozen of times, I chose to represent the list by a ul in which each li consists of a h3(name), a ul(properties) and a img(image).
In order to make it fill the page a bit more, I used CSS's flexbox in order to put the image and the properties next to each other in a responsive way.
img {
max-width: 100px;
}
#example > ul > li {
display: -webkit-flex;
display: flex;
-webkit-justify-content: space-around;
justify-content: space-around;
-webkit-align-items: center;
align-items: center;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
}
h3 {
width: 100%;
text-align: center;
}
div > ul {
border-left: 2px solid red;
}
<section id="example">
<ul>
<li>
<h3>Bulbasaur</h3>
<div>
<span>Properties</span>
<ul>
<li>green</li>
<li>seed</li>
<li>grass</li>
<li>poison</li>
</ul>
</div>
<img src="http://cdn.bulbagarden.net/upload/2/21/001Bulbasaur.png" />
</li>
<li>
<h3>Charmander</h3>
<div>
<span>Properties</span>
<ul>
<li>orange or some kind of red, I am not completely sure</li>
<li>lizard</li>
<li>fire</li>
</ul>
</div>
<img src="http://cdn.bulbagarden.net/upload/7/73/004Charmander.png" />
</li>
<li>
<h3>Squirtle</h3>
<div>
<span>Properties</span>
<ul>
<li>blue</li>
<li>tiny turtle</li>
<li>water</li>
</ul>
</div>
<img src="http://cdn.bulbagarden.net/upload/3/39/007Squirtle.png" />
</li>
</ul>
</section>
This looks pretty nice when the properties for all elements are equally long, but it kind of looks messy when this is not the case (the property-lists are not properly aligned as indicated by the red lines in the above snippet). I know I could get all the content in a table, causing every table element to be aligned nicely under each other, but then I don't know how I can have my names in a different line than the properties and the image...
My question could thus be formulated as:
How can I align the properties nicely under each other in such a way that they are displayed next to the image (to fill the space on the screen)? Additionally I would like that the image is displayed under the properties when the screen becomes too small (i.e. responsive design) and a separate line for the name.
Any help will be greatly appreciated
Update:
As it turned out that my question is not that clear, I tried to make it more clear by adding the vertical red lines in the snippet. I manage to get the desired result when using a table, but then I have to omit the names (as shown in the attached image) and the responsiveness...
You can just create a simple item element, something like this:
HTML
<li class="item">
<h2>Charmander</h2>
<div class="content">
<h3>Properties</h3>
<ul>
<li>orange or some kind of red, I am not completely sure</li>
<li>lizard</li>
<li>fire</li>
</ul>
</div>
<div class="image">
<img src="http://cdn.bulbagarden.net/upload/7/73/004Charmander.png" />
</div>
</li>
I simply divided the element in three main sections: title, properties and the image.
As you can see the properties are still inside a <ul> because they are used like a enumeration.
CSS
#example > ul {
padding: 0;
}
.item {
width: 100%;
background: #CCC;
padding: 20px;
box-sizing: border-box;
/* Padding will be inside the element (will not affect the width/height) */
margin: 20px 0;
overflow: hidden;
/* Used to keep the floated element inside the flow */
}
.item h2 {
text-align: center;
}
.item .content {
width: 60%;
float: left;
padding-left: 20px;
box-sizing: border-box;
}
.item .image {
width: 200px;
float: left;
}
.item img {
width: 100%;
}
.item .content ul {
border-left: 2px solid red;
margin-bottom: 20px;
}
With the first selector (#example > ul) I reset the default padding it has.
The text of the properties will just start on a new-line if it is too long (you can test this by resizing the window).
You can just edit the padding-left of the .content element, to move the properties a little bit more to the right or to the left.
Example JsFiddle
This is just to give you an example of how you want to approach this.
Hope it was helpful!
I have just been so stupid. As an alternative to the helpful answer of nkmol, it could also be as simple as changing the justify-content property to space-between and correct it by setting width and auto-margins.
img {
max-width: 100px;
}
#example > ul > li {
width: 80%;
margin: auto;
display: -webkit-flex;
display: flex;
-webkit-justify-content: space-between;
justify-content: space-between;
-webkit-align-items: center;
align-items: center;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
}
h3 {
width: 100%;
text-align: center;
}
li > div > ul {
border-left: 2px solid red;
}
<section id="example">
<ul>
<li>
<h3>Bulbasaur</h3>
<div>
<span>Properties</span>
<ul>
<li>green</li>
<li>seed</li>
<li>grass</li>
<li>poison</li>
</ul>
</div>
<img src="http://cdn.bulbagarden.net/upload/2/21/001Bulbasaur.png" />
</li>
<li>
<h3>Charmander</h3>
<div>
<span>Properties</span>
<ul>
<li>orange or some kind of red, I am not completely sure</li>
<li>lizard</li>
<li>fire</li>
</ul>
</div>
<img src="http://cdn.bulbagarden.net/upload/7/73/004Charmander.png" />
</li>
<li>
<h3>Squirtle</h3>
<div>
<span>Properties</span>
<ul>
<li>blue</li>
<li>tiny turtle</li>
<li>water</li>
</ul>
</div>
<img src="http://cdn.bulbagarden.net/upload/3/39/007Squirtle.png" />
</li>
</ul>
</section>
PS: I'm sorry for my awful question...
You need to break out your items from the primary UL
You can think of it as though you were building a table, but instead, use divs and then use a UL just to list the properties. This way, you can style each of the individual elements as needed.
look here: https://jsfiddle.net/oq04f6pm/2/
<section id="example">
<div class="section-title">Bulbasaur</div>
<div class="section-list">
<span>Properties</span>
<ul>
<li>green</li>
<li>seed</li>
<li>grass</li>
<li>poison</li>
</ul>
</div>
<div class="section-image">
<img src="http://cdn.bulbagarden.net/upload/2/21/001Bulbasaur.png" />
</div>
</section>
img {
max-width: 100px;
}
.section-title {
width: 100%;
text-align: center;
font-weight: bold;
}
.section-list, .section-image {
width: 50%;
float: left;
}
.section-image {
text-align: center;
}
#media screen and (max-width: 400px) {
.section-list, .section-image {
width: 100%;
}
.section-image {
text-align: left;
}
}

Can I have a line between rows of flexbox?

I have a horizontal navigation, which is somewhat long, and needs to be rearranged for narrow displays. I used flexbox to make it reflow into multiple rows.
But with many rows, the division between the navigation items is not so obvious. I tried giving them a border on top, and it kinda works - but the border is, of course, only visible over the individual navigation options, not creating a nice dividing line between all flexbox rows.
Please view the snippet full page, there is a display problem when it's viewed within the post. Or use this fiddle. You may have to make your browser window narrow to see the navigation in multi row.
header {
height: 3em;
background-color: #fff;
}
#main {
height: 9em;
background-color: #5987d1;
}
footer {
height: 3em;
background-color: #a8a8a8;
border-top: 1px solid #0047b9;
}
ul.horizontal-nav {
background: rgba(72, 72, 72, 1);
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-ms-flex-direction: row;
flex-direction: row;
align-items: center;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-shadow: 0px 2px 1px 0px rgba(0,0,0,0.75);
-moz-box-shadow: 0px 2px 1px 0px rgba(0,0,0,0.75);
box-shadow: 0px 2px 1px 0px rgba(0,0,0,0.75);
list-style: none;
}
li.NavigationLi2, li.selected-branch-root {
padding: 0.75em 1em;
display: block;
border-top: 1px solid #2662c3;
}
li.selected-branch-root {
background: #2662c3;
}
li.NavigationLi2 > a, li.NavigationLi2 > a:visited {
color: #e6eeff;
text-decoration: none;
-ms-word-wrap: nowrap;
word-wrap: nowrap;
}
li.selected-branch-root > a, li.selected-branch-root > a {
color: #fff;
text-decoration: none;
-ms-word-wrap: nowrap;
word-wrap: nowrap;
}
<header>
</header>
<nav class="horizontal-nav">
<ul class="horizontal-nav">
<li class="selected-branch-root">Search
</li>
<li class="NavigationLi2">My models
</li>
<li class="NavigationLi2">Account
</li>
<li class="NavigationLi2">Management
</li>
<li class="NavigationLi2">Administration
</li>
<li class="NavigationLi2">Help
</li>
</ul>
</nav>
<section id="main">
</section>
<footer>
</footer>
Here is what I do lets say I have a flexbox container with 3 divs inside
<div class="flex">
<div>
<h2>Free Shipping</h2>
</div>
<div>
<h2>Everything In Stock</h2>
</div>
<div>
<h2>Largest Inventory</h2>
</div>
</div>
What I am playing with is in order to make a line right in the middle of the 3 div's / flex items simply just add another flex item between the divs like this:
<div class="flex">
<div>
<h2>Free Shipping</h2>
</div>
<img src="lib/xxx/img/ydivider.png" alt="divider"/>
<div>
<h2>Everything In Stock</h2>
</div>
<img src="lib/xxx/img/ydivider.png" alt="divider"/>
<div>
<h2>Largest Inventory</h2>
</div>
</div>
You can now see we have 5 flex items instead of 3. The 2 additional flex items I find are spaced correctly to be in the middle. Keep in mind if you go to to a breakpoint where you display as columns you will need a horizontal img at that point.
Assuming your philosophy allows you to: 1) Use flebox instead or ul for navigation; and 2) insert tags in your html specifically for aesthetic purposes, then I have a sugestion.
Create a wrapping div to your elements and add to it the CSS you'd like to span the row (background, border, padding...), and add to it the property flex: 1. You might also want to add to it min-width: fit-content (or max-content) to keep it from breaking lines.
I've added below the markup that would show it before and after the quick fix.
#flex-container {
display: flex;
flex-wrap: wrap;
}
#flex-container > div {
padding: 8px 24px;
border-bottom: 4px solid orange;
background: purple;
}
.flex-menu {
font-size: 13px;
font-family: sans;
color: white;
}
.fix {
flex: 1;
min-width: fit-content;
}
.force-break {
max-width: 340px;
}
<div class="force-break">
<h2>Plain</h2>
<div id='flex-container'>
<div class="flex-menu">Search</div>
<div class="flex-menu">My models</div>
<div class="flex-menu">Account</div>
<div class="flex-menu">Management</div>
<div class="flex-menu">Administration</div>
<div class="flex-menu">Help</div>
</div>
<h2>With fix</h2>
<div id='flex-container'>
<div class="fix"><div class="flex-menu">Search</div></div>
<div class="fix"><div class="flex-menu">My models</div></div>
<div class="fix"><div class="flex-menu">Account</div></div>
<div class="fix"><div class="flex-menu">Management</div></div>
<div class="fix"><div class="flex-menu">Administration</div></div>
<div class="fix"><div class="flex-menu">Help</div></div>
</div>
</div>