I want to have multiple justified columns (fixed number of columns) for each list item, e.g.
- John 41 Singer
- Ringo 45 Drummer
can this be done with html/css? Perhaps an "li" class in CSS? It needs to be list items.
It's already been stated, but ideally this is a table of data and the right html for this should just be in a table. If you're against using a table in your html then the following solution should be fine. Update the container width for a wider layout.
Pen: https://codepen.io/joshuakelly/pen/dwBzdR
HTML:
<div class="wrapper">
<div class="row">
<div>John</div>
<div>41</div>
<div>Singer</div>
</div>
<div class="row">
<div>Ringo</div>
<div>45</div>
<div>Drummer</div>
</div>
</div>
<ul class="wrapper list">
<li class="row">
<div>John</div>
<div>41</div>
<div>Singer</div>
</li>
<li class="row">
<div>Ringo</div>
<div>45</div>
<div>Drummer</div>
</li>
</ul>
And the CSS
.wrapper {
display: flex;
flex-direction: column;
margin-bottom: 1em;
width: 300px
}
.wrapper.list {
list-style-type: none;
margin: 0;
padding: 0;
}
.row {
align-items: center;
display: flex;
justify-content: space-between;
}
.row div {
width: 33.33%
}
Just use a table...
<table>
<th>
<td>Name</td>
<td>Age</td>
<td>whateverelse</td>
</th>
<tr>
<td>John</td>
<td>45</td>
<td>i gues</td>
</tr>
</table>
Then use css to set fixed width for tabble and columns..
table {
border: 1px solid black;
table-layout: fixed;
width: 200px;
}
th, td {
border: 1px solid black;
width: 100px;
}
You could also, if your really in need it, just wrap the table inside the list like <ul><li><table>....</table></li></ul> That way you could style it anyway like you want using css...
List-version formatted as table and hacked to look also like a list (modified version of HermesTrismegistus ;)
ul.table-style {
display: table;
border: 1px solid black;
}
ul.table-style li:before {
display: list-item;
content: "";
}
ul.table-style li {
display: table-row;
}
ul.table-style span {
display: table-cell;
border: 1px solid black;
width: 100px;
}
<ul class="table-style">
<li>
<span>Name</span>
<span>Age</span>
<span>whateverelse</span>
</li>
<li>
<span>John</span>
<span>45</span>
<span>i gues</span>
</li>
</ul>
Related
I currently have text which looks like this. I want the 1600+ happy eaters to be all in one line. The title is fine as it is. I am currently using flexbox if this helps.
.currentcitiesmaincontent {
border: 1px solid red;
display: inline-flex;
width: 100%;
}
<div class="currentcitiesmaincontent">
<div>
Lisbon<br>
<p> 1600+ happy eaters</p>
</div>
<div>SAN Franscisco</div>
<div>Berlin</div>
<div>London</div>
</div>
You can set flex layout on inline divs too to make it on one line.
.currentcitiesmaincontent {
border: 1px solid red;
display: inline-flex;
width: 100%;
}
.currentcitiesmaincontent div {
display: flex;
}
.currentcitiesmaincontent p {
margin: 0;
padding: 0;
}
<div class="currentcitiesmaincontent">
<div>
Lisbon<br>
<p> 1600+ happy eaters</p>
</div>
<div>SAN Franscisco</div>
<div>Berlin</div>
<div>London</div>
</div>
i think this is what you are searching for
.currentcitiesmaincontent {
border: 1px solid red;
display: flex;
width: 100%;
}
.currentcitiesmaincontent > div:first-child{
display : flex;
}
* {
margin : 0px;
padding: 0px;
}
<div class="currentcitiesmaincontent">
<div>
Lisbon<br>
<p> 1600+ happy eaters</p>
</div>
<div>SAN Franscisco</div>
<div>Berlin</div>
<div>London</div>
</div>
You should create a class for the paragraph you want with white-space: nowrap;.
p.nowrap {
white-space: nowrap;
}
<p class="nowrap"> 1600+ happy eaters</p>
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>
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;
}
}
My web GUI's layout is partially driven by CSS tables. This is mainly because I want the "cells" to have the same height under all situations without any massive headaches surrounding alignment. Overall, this approach has been very successful.
However, I do have a problem whereby the right-hand cell in the table can sometimes take a moment to render, causing the left-hand cell to briefly have 100% of the page width. This causes a noticeable "flicker" effect which, although minor, is kind of annoying. And I've decided to fix it.
Here is a vague representation of how my page works:
#tbl { display: table; width: 200px; border: 1px solid black; }
#tbl-row { display: table-row; }
#tbl-col1,
#tbl-col2 { display: table-cell; }
#tbl-col1 { width: 50px; background-color: red; }
#tbl-col2 { background-color: blue; }
<div id="tbl">
<div id="tbl-row">
<div id="tbl-col1">LHS</div>
<div id="tbl-col2">RHS</div>
</div>
</div>
All's well and good until you use your developer tools to give #tbl-col2 a display: none directive, [I hope accurately] simulating the state of the browser's rendering engine in the moments between #tbl-col1 having been rendered, and #tbl-col2 being rendered.
Notice that #tbl-col1 immediately takes up 100% of the width of the table, despite the width I've given it. I sort of understand why this is happening: after all, I've asked the browser to make the divs behave like tables. Still, it's undesirable here.
I tried to fix this by inserting a "spacer", hoping that without a width it would expand to fill all the space on the right-hand side until such time as the right-hand side got rendered:
#tbl { display: table; width: 200px; border: 1px solid black; }
#tbl-row { display: table-row; }
#tbl-col1,
#tbl-spc,
#tbl-col2 { display: table-cell; }
#tbl-col1 { width: 50px; background-color: red; }
#tbl-col2 { width: 150px; background-color: blue; }
<div id="tbl">
<div id="tbl-row">
<div id="tbl-col1">LHS</div>
<div id="tbl-spc"></div>
<div id="tbl-col2">RHS</div>
</div>
</div>
As you can see by again hiding #tbl-col2, it made not a blind bit of difference: #tbl-col1 still took the whole width of the table, rather than the 50px I allowed it.
Assuming I'd rather fix this than abandon the CSS Tables layout altogether, what can I do?
Or am I going to have to replace the layout or, even worse, take a JavaScript approach to resolving the FoUC?
What I like to do in similar cases (for example html emails) is to pre-define column widths using empty cells this way:
.tbl {
display: table;
width: 200px;
border: 1px solid black;
color: #fff;
}
.tbl-row {
display: table-row;
}
.tbl-cell {
display: table-cell;
}
.tbl-col1 {
width: 50px;
background-color: red;
}
.tbl-col2 {
background-color: blue;
}
<h3>Pre-define columns width by adding additional row</h3>
<div class="tbl">
<div class="tbl-row tbl-format">
<div class="tbl-cell tbl-col1"></div>
<div class="tbl-cell tbl-col2"></div>
</div>
<div class="tbl-row">
<div class="tbl-cell tbl-col1">LHS</div>
<div class="tbl-cell tbl-col2">RHS</div>
</div>
</div>
That formatting column is invisible if there is no content inside cells, but still it tells browser the way table should be formatted.
That's because, by default, tables use the automatic table layout.
The CSS 2.1 spec doesn't define that layout mode, but suggests a (non-normative) algorithm, which reflects the behavior of several popular HTML user agents.
According to that algorithm,
If the used width is greater than MIN, the extra width should be
distributed over the columns.
However, it doesn't explain how it should be distributed. In fact, your attempt of inserting a "spacer" element works perfectly on Firefox, but not on Chrome.
Instead, you may want to try the fixed table mode, which is properly defined in the spec (and thus more reliable), is usually faster, and solves the problem too:
In the fixed table layout algorithm, the width of each column is
determined as follows:
A column element with a value other than auto for the width property sets the width for that column.
Otherwise, a cell in the first row with a value other than auto for the width property determines the width for that column. If
the cell spans more than one column, the width is divided over the
columns.
Any remaining columns equally divide the remaining horizontal table space (minus borders or cell spacing).
According to the 3rd point, the spacer element will receive the remaining 150px before the last cell has been loaded. And will receive the remaining 0px once loaded.
So you need
#tbl { table-layout: fixed; }
.tbl {
display: table;
table-layout: fixed;
width: 200px;
border: 1px solid black;
}
.tbl-row {
display: table-row;
}
.tbl-col1,
.tbl-spc,
.tbl-col2 {
display: table-cell;
}
.tbl-col1 {
width: 50px;
background-color: red;
}
.tbl-col2 {
width: 150px;
background-color: blue;
}
.hide {
display: none;
}
While parsing the first cell:
<div class="tbl">
<div class="tbl-row">
<div class="tbl-col1">LHS</div>
<div class="tbl-spc hide"></div>
<div class="tbl-col2 hide">RHS</div>
</div>
</div>
While parsing the spacer:
<div class="tbl">
<div class="tbl-row">
<div class="tbl-col1">LHS</div>
<div class="tbl-spc"></div>
<div class="tbl-col2 hide">RHS</div>
</div>
</div>
While parsing the second cell:
<div class="tbl">
<div class="tbl-row">
<div class="tbl-col1">LHS</div>
<div class="tbl-spc"></div>
<div class="tbl-col2">RHS</div>
</div>
</div>
However, there is still a problem: the spacer won't be displayed until the first cell has been parsed completely.
That means the spacer must be loaded first, but must not be the first to be displayed. Sadly, the CSS table layout does not allow to reorder the cells. But it can be achieved by removing the non-semantic spacer from the HTML and using an ::after pseudo-element instead:
#tbl-row:after {
content: '';
display: table-cell;
}
.tbl {
display: table;
table-layout: fixed;
width: 200px;
border: 1px solid black;
}
.tbl-row {
display: table-row;
}
.tbl-row:after {
content: '';
display: table-cell;
}
.tbl-col1,
.tbl-col2 {
display: table-cell;
}
.tbl-col1 {
width: 50px;
background-color: red;
}
.tbl-col2 {
width: 150px;
background-color: blue;
}
.hide {
display: none;
}
While parsing the first cell:
<div class="tbl">
<div class="tbl-row">
<div class="tbl-col1">LHS</div>
<div class="tbl-col2 hide">RHS</div>
</div>
</div>
While parsing the second cell:
<div class="tbl">
<div class="tbl-row">
<div class="tbl-col1">LHS</div>
<div class="tbl-col2">RHS</div>
</div>
</div>
would this be a reasonable fix?
#tbl { display: table; width: 200px; border: 1px solid black; }
#tbl-row { display: flex; }
#tbl-col1,
#tbl-spc,
#tbl-col2 {
flex:0;
overflow:hidden
}
#tbl-col1 { flex-basis: 50px; background-color: red; }
#tbl-col2 { flex-basis: 150px; background-color: blue; }
<div id="tbl">
<div id="tbl-row">
<div id="tbl-col1">LHS-LHS-LHS-LHS</div>
<div id="tbl-spc"></div>
<div id="tbl-col2">RHS</div>
</div>
</div>
EDIT:
here's a fiddle with prefixes and fallback
Wanna try this -
JS Fiddle
.tbl{display:table;}
.fixed{width: 200px; border: 1px solid black; }
.tblRow { display: table-row; }
.tblCol{ display: table-cell; }
.col1 .tbl { width: 50px; background-color: red; }
.col2 .tbl { width: 150px; background-color: blue; display:none; }
As I said in my comment, Play with the table width. So here it is. Remove display:none from style line .col2 .tbl { width: 150px; background-color: blue; display:none; } and all you can see. this is perhaps what you want.
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>