Multi-line flexbox list with text-overflow: ellipsis - css

I would like to achieve the attached list style in HTML5/CSS.
The single-line items can easily be done using flexbox (see below). However, I cannot quite figure out how to achieve the double-line items: If I allow wrapping, the "List Item Title" will no longer be truncated (ellipsis)...
Should I use CSS grid? Or is that overkill?
Here is my flexbox-single-line-implementation:
ul {
padding: 0;
border: 1px solid red;
list-style-type: none;
}
li {
display: flex;
margin: 0;
border-bottom: 1px solid gray;
}
div.icon {
flex-shrink: 0;
width: 20px;
height: 20px;
margin: 15px;
background-color: lightcoral;
}
span.title {
flex-grow: 1;
flex-shrink: 1;
margin: 15px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
span.tag {
flex-shrink: 0;
margin: 15px;
}
span.second-line {
margin: 15px;
}
<ul>
<li>
<div class="icon"></div>
<span class="title">List Item Title</span>
<span class="tag">Some tag</span>
</li>
<li>
<div class="icon"></div>
<span class="title">Very Super Long List Item Title With Added Characters to Ensure Truncation</span>
<span class="tag">Some tag</span>
</li>
<li>
<div class="icon"></div>
<span class="title">List Item Title</span>
</li>
</ul>

You can achieve the result by using two child Div's inside li and have separate Flex for both child Div's instead having in li. Find the code below which works for me.
Code:
ul {
padding: 0;
border: 1px solid red;
list-style-type: none;
}
li {
margin: 0;
border-bottom: 1px solid gray;
}
div.icon {
flex-shrink: 0;
width: 20px;
height: 20px;
margin: 15px;
background-color: lightcoral;
}
span.title {
flex-grow: 1;
flex-shrink: 1;
margin: 15px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
span.tag {
flex-shrink: 0;
margin: 15px;
}
span.second-line {
margin: 15px;
}
.mainHeading {
display: flex;
}
.subHeading {
display: block;
}
<ul>
<li>
<div class="mainHeading">
<div class="icon"></div>
<span class="title">List Item Title</span>
<span class="tag">Some tag</span>
</div>
</li>
<li>
<div class="mainHeading">
<div class="icon"></div>
<span class="title">Very Super Long List Item Title With Added Characters to Ensure Truncation</span>
<span class="tag">Some tag</span>
</div>
<div class="subHeading">
<span class="title">List Item Sub Title</span>
<span class="tag">Some another tag</span>
</div>
</li>
<li>
<div class="mainHeading">
<div class="icon"></div>
<span class="title">List Item Title</span>
</div>
</li>
</ul>

Related

Make floating items remain the original position vertically

I have the following HTML
ul {
margin: 0;
padding: 0;
list-style: none;
font-size: 12px;
display: inline-block;
}
li {
display: inline-block;
padding: 0 5px;
}
.number {
float:right;
}
.rec {
float: left;
}
<div style="background-color: grey;">
<span style="font-size:16px">Text</span>
<ul>
<li>10</li>
<li>records</li>
</ul>
</div>
<br>
<div style="background-color: grey;">
<span style="font-size:16px">Text</span>
<ul>
<li class="number">10</li>
<li class="rec">records</li>
</ul>
</div>
When the list item floats, they move higher vertically, See this screenshot
Here is the jsfiddle link:
https://jsfiddle.net/mddc/d193a4v8/1/
How to make floating items remain the original position vertically?
You can adjust the line-height and reduce it to line-height: 8px for the property ul and it should align it properly as follows:
ul {
margin: 0;
padding: 0;
list-style: none;
font-size: 12px;
display: inline-block;
line-height: 8px;
}
li {
display: inline-block;
padding: 0 5px;
}
.number {
float:right;
}
.rec {
float: left;
}
<div style="background-color: grey;">
<span style="font-size:16px">Text</span>
<ul>
<li>10</li>
<li>records</li>
</ul>
</div>
<br>
<div style="background-color: grey;">
<span style="font-size:16px">Text</span>
<ul>
<li class="number">10</li>
<li class="rec">records</li>
</ul>
</div>

Vertically center content inside an inline parent

Trying to create an adaptive post meta for a post card.
The idea is that sometimes the post meta could have more than one category inside and because of that I need somehow to wrap the items, but at the same time to vertically center the li content (like the avatar and icons).
I tried to apply display: inline-flex to the .entry-meta in order to be able to use the align-items: center property but in this case the list items - li's are not anymore wrapping nice like when applying display: inline to li.
1. The display: inline method (not centering items vertically)
This method is wrapping correctly and how I want all the list items but it can't center vertically the content (like the avatar and icons)
article {
max-width: 450px;
background: #eee;
font-family: arial;
font-size: 12px;
text-transform: uppercase;
}
article a {
text-decoration: none;
}
.entry-meta {
list-style: none;
margin: 0;
padding: 0;
}
.entry-meta li {
display: inline;
margin-right: 10px;
background: #ccc;
}
.avatar {
display: inline-block;
width: 25px;
height: 25px;
border-radius: 100%;
background: #FA7059;
}
.icon {
display: inline-block;
width: 13px;
height: 13px;
background: #BE4C4E;
}
<article>
<ul class="entry-meta">
<li class="author">
<div class="avatar">
</div>
<span>By </span>
Admin
</li>
<li class="date">
<span>On </span>
<time>Feb 22, 2019</time>
</li>
<li>
<span>On </span>
2 Comments
</li>
<li class="categories">
<span class="icon">
</span>
Food
Nature
People
Travel
Trends
Business
Sport
Music
Gadgets
Uncategorized
</li>
<li class="tags">
<span class="icon">
</span>
Red
Blue
Green
Yellow
</li>
</ul>
</article>
2. The display: inline-flex method
The category li is not wrapped correctly, it breaks in a new line, but in exchange the content is vertically centered like I need.
article {
max-width: 450px;
background: #eee;
font-family: arial;
font-size: 12px;
text-transform: uppercase;
}
article a {
text-decoration: none;
}
.entry-meta {
list-style: none;
margin: 0;
padding: 0;
display: inline-flex;
flex-wrap: wrap;
align-items: center;
}
.entry-meta li {
margin-right: 10px;
background: #ccc;
display: inline-flex;
flex-wrap: wrap;
align-items: center;
}
.avatar {
display: inline-block;
width: 25px;
height: 25px;
border-radius: 100%;
background: #FA7059;
}
.icon {
display: inline-block;
width: 13px;
height: 13px;
background: #BE4C4E;
}
<article>
<ul class="entry-meta">
<li class="author">
<div class="avatar">
</div>
<span>By </span>
Admin
</li>
<li class="date">
<span>On </span>
<time>Feb 22, 2019</time>
</li>
<li>
<span>On </span>
2 Comments
</li>
<li class="categories">
<span class="icon">
</span>
Food
Nature
People
Travel
Trends
Business
Sport
Music
Gadgets
Uncategorized
</li>
<li class="tags">
<span class="icon">
</span>
Red
Blue
Green
Yellow
</li>
</ul>
</article>
So, in other words, I need somehow to keep the list items to wrap like they are with display: inline but at the same time center vertically the content inside.
P.S. the vertical-align: middle property doesn't really help :)
P.S. the vertical-align: middle property doesn't really help :)
This is actually what you need (applied to .avatar)
article {
max-width: 450px;
background: #eee;
font-family: arial;
font-size: 12px;
text-transform: uppercase;
}
article a {
text-decoration: none;
}
.entry-meta {
list-style: none;
margin: 0;
padding: 0;
}
.entry-meta li {
display: inline;
margin-right: 10px;
background: #ccc;
}
.avatar {
display: inline-block;
width: 25px;
height: 25px;
border-radius: 100%;
background: #FA7059;
vertical-align:middle;
}
.icon {
display: inline-block;
width: 13px;
height: 13px;
background: #BE4C4E;
}
<article>
<ul class="entry-meta">
<li class="author">
<div class="avatar">
</div>
<span>By </span>
Admin
</li>
<li class="date">
<span>On </span>
<time>Feb 22, 2019</time>
</li>
<li>
<span>On </span>
2 Comments
</li>
<li class="categories">
<span class="icon">
</span>
Food
Nature
People
Travel
Trends
Business
Sport
Music
Gadgets
Uncategorized
</li>
<li class="tags">
<span class="icon">
</span>
Red
Blue
Green
Yellow
</li>
</ul>
</article>

css flex - make gap between divs

When in a landscape mode, I need to separate/make a gap (around 10-20px) between the two columns without using a border or anything like that. I tried everything and it still doesn't work, what am i missing? I tried putting margins, but it doesn't help, what's the best way to solve this?
#media screen and (min-width: 567px) {
.container {
display: flex;
flex-flow: row wrap;
}
.container li {
flex-basis: 50%;
max-width: 50%;
}
}
.item {
display: flex;
align-items: center;
padding-top: 5px;
}
.title {
font-weight: 500;
font-size: 22px;
padding-bottom: 18px;
}
.item-image {
flex-basis: 85px;
min-width: 85px;
padding-bottom: 30px;
}
.item .item-image img {
display: inline-block;
vertical-align: middle;
border-radius: 20px;
width: 100%;
}
.item .item-info {
border-bottom: 1px solid rgb(207, 206, 206);
padding-bottom: 20px;
flex-basis: 100%;
margin-left: 15px;
}
<ul class="container">
<li>
<div class="item">
<div class="item-image">
<a href="">
<img src="root-icon.png" alt="">
</a>
</div>
<div class="item-info">
<div class="item-title">Something</div>
<div class="item-subtitle">Something</div>
<div class="item-button-container">
<a class="button" href="#">GET</a>
</div>
</div>
</div>
</li>
<li>
<div class="item">
<div class="item-image">
<a href="">
<img src="root-icon.png" alt="">
</a>
</div>
<div class="item-info">
<div class="item-title">Something</div>
<div class="item-subtitle">Something</div>
<div class="item-button-container">
<a class="button" href="#">GET</a>
</div>
</div>
</div>
</li>
</ul>
Just add something like gap: 5px to your container with flex layout
Thanks to #AbsoluteBeginner this feature is supported not everywhere. See here: https://caniuse.com/flexbox-gap
Add margin-right to the element if you want to stick to flexbox.
Otherwise - try out css grid, super easy with grid-gap to add the gap you need.
https://www.w3schools.com/css/css_grid.asp
You can add this CSS rule:
ul.container > *:nth-child(odd) .item-info {
margin-right: 50px;
}
It adds a right marging to every odd .item-info (or more precisely: to every .item-info inside every odd direct child element of the .container element)
#media screen and (min-width: 567px) {
.container {
display: flex;
flex-flow: row wrap;
}
.container li {
flex-basis: 50%;
max-width: 50%;
}
}
.item {
display: flex;
align-items: center;
padding-top: 5px;
}
.title {
font-weight: 500;
font-size: 22px;
padding-bottom: 18px;
}
.item-image {
flex-basis: 85px;
min-width: 85px;
padding-bottom: 30px;
}
.item .item-image img {
display: inline-block;
vertical-align: middle;
border-radius: 20px;
width: 100%;
}
.item .item-info {
border-bottom: 1px solid rgb(207, 206, 206);
padding-bottom: 20px;
flex-basis: 100%;
margin-left: 15px;
}
ul.container > *:nth-child(odd) .item-info {
margin-right: 50px;
}
<ul class="container">
<li>
<div class="item">
<div class="item-image">
<a href="">
<img src="root-icon.png" alt="">
</a>
</div>
<div class="item-info">
<div class="item-title">Something</div>
<div class="item-subtitle">Something</div>
<div class="item-button-container">
<a class="button" href="#">GET</a>
</div>
</div>
</div>
</li>
<li>
<div class="item">
<div class="item-image">
<a href="">
<img src="root-icon.png" alt="">
</a>
</div>
<div class="item-info">
<div class="item-title">Something</div>
<div class="item-subtitle">Something</div>
<div class="item-button-container">
<a class="button" href="#">GET</a>
</div>
</div>
</div>
</li>
</ul>

Placing elemenents with css?

I want to place image floated left, next to image, floated left one under another would be Authro, Date and Category, than, after this other elements will be floated on right side...
Like this...
https://i.imgur.com/tcKwalP.png
This is what I have so far...
https://jsfiddle.net/fbn9r3y4/
This is html...
<div class="entry-meta">
<span class="entry-image">
<a class="entry-image-a" href="">
<img src="image.jpg" height="48" width="48">
</a>
</span>
<span class="entry-author">
Ester
</span>
<span class="entry-date">September 3, 2019</span>
<span class="entry-category-single">
Music
</span>
<span class="meta-right">
<span class="entry-views"><span class="view-count">998</span> Views</span>
<span class="entry-like">
<span class="sl-wrapper">
<a href="" class="sl-button">
<span class="sl-count">500<em>Likes</em></span>
</a>
<span class="sl-loader"></span>
</span>
</span>
</span>
</div>
This is css...
.entry-meta {
font-family: Arial, sans-serif;
display: block;
align-items: center;
border-top: 1px solid #f3f3f3;
border-bottom: 1px solid #f3f3f3;
padding: 10px 2px;
}
.entry-image {
display: block;
float: left;
}
.entry-author {
display: block;
float: left;
width: 200px;
}
.entry-date {
display: block;
float: left;
width: 200px;
clear: left;
}
.entry-category-single {
display: block;
float: left;
width: 200px;
clear: left;
}
.meta-right {
margin: 0 10px 0 0;
margin-left: auto;
order: 2;
float: right;
}
.entry-like {
min-width: 32px;
line-height: 1;
float: right;
clear: right;
}
.entry-views {
min-width: 32px;
line-height: 1;
float: right;
clear: right;
}
I changed up your markup a little bit and added a wrapping meta-left around the content of the left side. I also simplified your CSS. There were several CSS properties that were invalid or not necessary.
.entry-meta {
font-family: Arial, sans-serif;
border-top: 1px solid #f3f3f3;
border-bottom: 1px solid #f3f3f3;
padding: 10px 2px;
}
.entry-meta::after {
content: '';
clear: both;
display: block;
}
.meta-left {
float: left;
}
.meta-right {
float: right;
margin: 0 10px 0 0;
}
.entry-image {
float: left;
}
.meta-info {
float: left;
margin-left: 10px;
}
.entry-like {
min-width: 32px;
line-height: 1;
}
.entry-views {
min-width: 32px;
line-height: 1;
}
<div class="entry-meta">
<div class="meta-left">
<div class="entry-image">
<a class="entry-image-a" href="">
<img src="https://via.placeholder.com/48" height="48" width="48">
</a>
</div>
<div class="meta-info">
<div class="entry-author">
Ester
</div>
<div class="entry-date">September 3, 2019</div>
<div class="entry-category-single">
Music
</div>
</div>
</div>
<div class="meta-right">
<div class="entry-views"><span class="view-count">998</span> Views</div>
<div class="entry-like">
<span class="sl-wrapper">
<a href="" class="sl-button">
<span class="sl-count">500<em> Likes</em></span>
</a>
<span class="sl-loader"></span>
</span>
</div>
</div>
</div>
Here's a version using display: flex that's even simpler. Same markup.
.entry-meta {
font-family: Arial, sans-serif;
border-top: 1px solid #f3f3f3;
border-bottom: 1px solid #f3f3f3;
padding: 10px 2px;
display: flex;
flex-direction: row;
justify-content: space-between;
}
.meta-left {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.meta-info {
margin-left: 10px;
}
<div class="entry-meta">
<div class="meta-left">
<div class="entry-image">
<a class="entry-image-a" href="">
<img src="https://via.placeholder.com/48" height="48" width="48">
</a>
</div>
<div class="meta-info">
<div class="entry-author">
Ester
</div>
<div class="entry-date">September 3, 2019</div>
<div class="entry-category-single">
Music
</div>
</div>
</div>
<div class="meta-right">
<div class="entry-views"><span class="view-count">998</span> Views</div>
<div class="entry-like">
<span class="sl-wrapper">
<a href="" class="sl-button">
<span class="sl-count">500<em> Likes</em></span>
</a>
<span class="sl-loader"></span>
</span>
</div>
</div>
</div>
Esteros. Please check this link
https://codepen.io/juricon/pen/QWLOZea
HTML:
<div class="entry-meta">
<span class="entry-image">
<a class="entry-image-a" href="">
<img src="image.jpg" height="48" width="48">
</a>
</span>
<ul class="left-float-list">
<ol>
<a href="" title="" rel="author">
Ester
</a>
</ol>
<ol>
September 3, 2019
</ol>
<ol>
<a href="">
Music
</a>
</ol>
</ul>
<ul class="right-float-list">
<li class="items-reverse">
<span class="entry-views">
<!--do not miss nesting rules <tag><tag1></tag1</tag> -->
998
</span>
<span class="view-count">
Views
</span>
</li>
<li>
<span class="entry-like">
<span class="sl-wrapper"> <!--do not miss nesting rules <tag><tag1></tag1</tag> Also, you don't have in CSS classes like .sl-wrapper .sl-button, .sl-count, sl-loader -->
<a href="" class="sl-button">
<span class="sl-count">
500<em>Likes</em>
</span>
<!-- it is a bad idea to use <em> with not cursive text in one <span>. Use CSS to style your text -->
</a>
<span class="sl-loader">
</span>
</span>
</span>
</li>
<li>
Whatever
</li>
</ul>
CSS:
*{ /*clear styles*/
margin:0;
padding:0;
/*clear styles*/
}
.entry-meta {
font-family: Arial, sans-serif;
display: block;
border-top: 1px solid #f3f3f3;
border-bottom: 1px solid #f3f3f3;
padding: 10px 2px;
}
.entry-image{
float: left;
}
.left-float-list{
float: left;
width: 200px;
list-style:none;
background: green;
margin-left:.4em;
}
.right-float-list{
float: right;
list-style:none;
background: red;
margin-right:1em;
}
.entry-views, .entry-like {
min-width: 32px;
line-height: 1;
}
Esteros, here you will find a great web development free course https://www.freecodecamp.org/ and
https://www.w3schools.com/html/default.asp.
It will help you a lot. Good luck!
P.S.: Use Flexbox instead of "float" and you won't regret.

How to spread elements with flex to take up the same width in a parent container

My codepen
What I want to achieve:
I want that the elements within the process-indicator parent take up the same width except the elements with class=step AND that the divs with steps name are directly under the step element.
The process-indicator stretch 100% and the connector classes should not use fixed pixel widths so I can add 5,6 or 10 steps and it scales graphically well.
What does not work:
1.) The first after-connector and last before-connector elements in yellow do not share the same size as the elements in green/black
2.) The step names in the divs should be positioned under the according step bubble and not inline with the steps and connectors.
Be aware that I do NOT want to use the before/after pseudo selectors for the step element! =>
I need to be able to later apply dynamically a complete/incomplete class with react thus I need full control about every connector.
HTML
<ul class="process-indicator">
<li class="completed">
<span class="step"></span>
<span class="after-connector"></span>
<div>step 1</div>
</li>
<li class="incompleted">
<span class="before-connector"></span>
<span class="step"></span>
<span class="after-connector"></span>
<div>step 2</div>
</li>
<li class="incompleted">
<span class="before-connector"></span>
<span class="step"></span>
<span class="after-connector"></span>
<div>step 3</div>
</li>
<li class="incompleted">
<span class="before-connector"></span>
<span class="step"></span>
<div>step 4</div>
</li>
</ul>
SCSS
$incomplete: gray;
$complete: blue;
$step-size: 40px;
$step-line-thickness: 2px;
$border-thickness: 1px;
$darken-amount: 30%;
#mixin step-style($color) {
background-color: $color;
color: $color;
border-color: darken($color, $darken-amount);
&:before,
&:after {
background-color: $color;
border-color: darken($color, $darken-amount);
}
}
.flex {
-ms-flex: 1;
-webkit-flex: 1;
-moz-flex: 1;
flex: 1;
}
.displayFlex {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
.process-indicator {
background: orange;
#extend .displayFlex;
margin: 0;
padding: 0;
margin-bottom: 1em;
> li {
#extend .displayFlex;
#extend .flex;
list-style: none;
font-size: 1.2em;
position: relative;
text-overflow: ellipsis;
color: $incomplete;
}
> li .before-connector,
li .after-connector {
#extend .flex;
position: relative;
text-overflow: ellipsis;
color: $incomplete;
}
> li .step {
width: $step-size;
height: $step-size;
background-color: $incomplete;
border-radius: 40px;
}
// line connectors
> li .after-connector {
height: 3px;
top: $step-size / 2;
background-color: green;
}
> li .before-connector {
height: 3px;
top: $step-size / 2;
background-color: red;
}
> li:first-child span.after-connector,
> li:last-child span.before-connector {
background: yellow;
}
// completed state
> li.completed {
color: $complete;
.step {
#include step-style($complete);
}
}
> li.incompleted {
color: $incomplete;
.step {
#include step-style($incomplete);
}
}
}
UPDATE
I would go with a flex solution on the container and move the seperators outside so they can grow equally:
.container {
display: flex;
width: 100%;
background: orange;
}
.step {
height: 40px;
width: 40px;
border-radius: 50%;
overflow: visible;
position: relative;
background: grey;
}
.text {
font-weight:bold;
font-size:20px;
position: absolute;
top: 100%;
margin-top: 10px;
left: 0;
white-space: nowrap;
}
.step:last-child .text {
right:0;
left:auto;
}
.seperator {
flex-grow: 1;
position: relative;
}
.seperator:before {
content: '';
display: block;
height: 10px;
position: absolute;
left: 0;
right: 0;
top: 50%;
transform: translateY(-50%);
}
.yellow:before {
background: yellow;
}
.green:before {
background: green;
}
.red:before {
background: red;
}
<div class="container">
<div class="step">
<span class="text">Step 1</span>
</div>
<div class="seperator yellow"></div>
<div class="seperator red"></div>
<div class="step">
<span class="text">Step 2</span>
</div>
<div class="seperator green"></div>
<div class="seperator red"></div>
<div class="step">
<span class="text">Step 3</span>
</div>
<div class="seperator green"></div>
<div class="seperator yellow"></div>
<div class="step">
<span class="text">Step 4</span>
</div>
</div>
Please note you will need to add margin bottom to the container to prevent any content below being overlapped by the text

Resources