CSS alternate row order for display:table - html

I have an HTML page with a list of items and their descriptions. The styling is done exclusively in CSS, in the pursuit of keeping information separate from layout.
Is it possible to use only CSS so that for every other row, the columns are reversed? I'd like to avoid using an HTML table, or manually reversing the columns in HTML, and I'd like to keep using <ul> and <li>, since it matches the kind of data that is displayed.
What I have:
img {
max-width: 50px;
height: auto;
}
ul {
list-style-type: none;
border-collapse: collapse;
display: table;
}
.item-name, .item-details {
display: table-row;
}
.item-pic, .item-text {
display: table-cell;
vertical-align: top;
padding: 10px;
}
.item-name {
font-weight: bold;
}
<html>
<body>
<ul>
<li><span class="item-pic"><img src="green.gif"></span>
<span class="item-text">
<span class="item-name">Green</span>
<span class="item-details">This is a green item</span>
</span>
</li>
<li><span class="item-pic"><img src="red.gif"></span>
<span class="item-text">
<span class="item-name">Red</span>
<span class="item-details">This is a red item</span>
</span>
</li>
<li><span class="item-pic"><img src="blue.gif"></span>
<span class="item-text">
<span class="item-name">Blue</span>
<span class="item-details">This is a blue item</span>
</span>
</li>
<li><span class="item-pic"><img src="yellow.gif"></span>
<span class="item-text">
<span class="item-name">Yellow</span>
<span class="item-details">This is a yellow item</span>
</span>
</li>
</ul>
</body>
</html>
What I would like:

You can use the following CSS code. It uses display:flex on the li tags, with reverse order on every second one (:nth-child(even)) , and display: block on the two text spans to make them go across the whole width of their parent and therefore place them below each other. Other details see below:
(The width of the container can be adjusted as desired, it could as well be 100% to span the whole width of its parent)
img {
max-width: 50px;
height: auto;
}
ul {
list-style-type: none;
display: block;
width: 200px;
padding: 0;
}
ul>li {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
ul>li:nth-child(even) {
flex-direction: row-reverse;
}
.item-text > * {
display: block;
}
.item-pic,
.item-text {
padding: 10px;
}
.item-name {
font-weight: bold;
}
<html>
<body>
<ul>
<li>
<span class="item-pic"><img src="green.gif"></span>
<span class="item-text">
<span class="item-name">Green</span>
<span class="item-details">This is a green item</span>
</span>
</li>
<li><span class="item-pic"><img src="red.gif"></span>
<span class="item-text">
<span class="item-name">Red</span>
<span class="item-details">This is a red item</span>
</span>
</li>
<li><span class="item-pic"><img src="blue.gif"></span>
<span class="item-text">
<span class="item-name">Blue</span>
<span class="item-details">This is a blue item</span>
</span>
</li>
<li><span class="item-pic"><img src="yellow.gif"></span>
<span class="item-text">
<span class="item-name">Yellow</span>
<span class="item-details">This is a yellow item</span>
</span>
</li>
</ul>
</body>
</html>

You can do it with a combination of nth-child and flex. With nth-child, you can easily target alternating rows with odd or even keywords. Then it just a matter of setting the li to flex and changing the order for even row. (EDIT: updated this to use row reverse instead as it is indeed easier)
I removed all the able related styles
img {
max-width: 50px;
height: auto;
}
ul {
list-style-type: none;
border-collapse: collapse;
}
.item-pic,
.item-text {
padding: 10px;
}
.item-name {
font-weight: bold;
display: block; // no need for this if you use a div
}
li {
display: flex;
}
li:nth-child( even ) {
flex-direction: row-reverse;
}
<html>
<body>
<ul>
<li><span class="item-pic"><img src="green.gif"></span>
<span class="item-text">
<span class="item-name">Green</span>
<span class="item-details">This is a green item</span>
</span>
</li>
<li><span class="item-pic"><img src="red.gif"></span>
<span class="item-text">
<span class="item-name">Red</span>
<span class="item-details">This is a red item</span>
</span>
</li>
<li><span class="item-pic"><img src="blue.gif"></span>
<span class="item-text">
<span class="item-name">Blue</span>
<span class="item-details">This is a blue item</span>
</span>
</li>
<li><span class="item-pic"><img src="yellow.gif"></span>
<span class="item-text">
<span class="item-name">Yellow</span>
<span class="item-details">This is a yellow item</span>
</span>
</li>
</ul>
</body>
</html>

Related

why border bottom is wider than list content?

I have a list and I want to apply border bottom to it, here is what I want
here is what I have so far.
here is jsfiddle: https://jsfiddle.net/Mwanitete/vr1c8tgo/10/
.data-right-bottom ul li {
margin: 10px;
list-style-type: none;
display: flex;
width: 400px;
border-bottom: 1px solid green;
}
.data-right-bottom ul li span {
flex: 1 0 0;
width: 400px;
}
<div class="data-right-bottom">
<ul>
<li style="display: none;">
<span>Total wrapping (tax incl.)</span>
<span id="total_wrapping_right" class="total_wrapping_right">0,00 zł</span>
</li>
<li>
<span>Total products (tax incl.)</span>
<span id="total_product_right" class="total_product_wt_right">210,00 zł</span>
</li>
<li>
<span>Total shipping (tax incl.)</span>
<span class="total_shipping_right">
12,00 zł
</span>
</li>
<li class="order-subtotal">
<span>Total (tax excl.)</span>
<span class="total_price_without_tax_right">182,73 zł</span>
</li>
<li class="order-discounts" style="display:none">
<span>Total discounts</span>
<span class="total_discount_right">0,00 zł</span>
</li>
<li class="order-tax">
<span>Total tax</span>
<span class="total_tax_right">39,27 zł</span>
</li>
<li class="order-total">
<span>Total</span>
<span class="total_price_right">222,00 zł</span>
</li>
</ul>
</div>
what am i missing here? any help will be apreciated
Another option besides Lazar Nikolic's one is to use a CSS table instead of a flexbox. After all, that's what it is; it displays tabular data.
To make it responsive as you wanted, you can always use a media query to turn it back into a series of blocks so that everything is displayed underneath each other.
.data-right-bottom ul {
display: table;
}
.data-right-bottom ul li {
list-style-type: none;
display: table-row;
}
.data-right-bottom ul li span {
display: table-cell;
border-top: 1px solid green;
}
.data-right-bottom ul li span:last-child {
padding-left: 10px;
text-align: right;
}
#media all and (max-width: 17em) {
.data-right-bottom ul li {
display: block;
border-top: 1px solid green;
}
.data-right-bottom ul li span {
display: block;
border-top: none;
}
}
<div class="data-right-bottom">
<ul>
<li style="display: none;">
<span>Total wrapping (tax incl.)</span>
<span id="total_wrapping_right" class="total_wrapping_right">0,00 zł</span>
</li>
<li>
<span>Total products (tax incl.)</span>
<span id="total_product_right" class="total_product_wt_right">210,00 zł</span>
</li>
<li>
<span>Total shipping (tax incl.)</span>
<span class="total_shipping_right">
12,00 zł
</span>
</li>
<li class="order-subtotal">
<span>Total (tax excl.)</span>
<span class="total_price_without_tax_right">182,73 zł</span>
</li>
<li class="order-discounts" style="display:none">
<span>Total discounts</span>
<span class="total_discount_right">0,00 zł</span>
</li>
<li class="order-tax">
<span>Total tax</span>
<span class="total_tax_right">39,27 zł</span>
</li>
<li class="order-total">
<span>Total</span>
<span class="total_price_right">222,00 zł</span>
</li>
</ul>
</div>
The problem is within your css class for
.data-right-bottom ul li span. Delete it.
Also, under display: flex in .data-right-bottom ul li you should say justify-content: space-between to separate two spans that you have inside. This will give you borders that are as long as your content is. I suppose you used flex: 1 0 0; in order for your list to be responsive, but it could not be done considering that you said that the width of your list item should be 400px.
It looks like that you're trying to create a table - aren't you? If yes, you should use an HTML table instead of a list.
Especially if you want that the content in the last column has text-align: left; but the whole column be aligned to the right border of your block.
List items (li inside ul) are independent of each other and you can't make one span inside li to have the same variable width depend on the width of the span in other li. Table row, in contrast, changes the width based on its content.
table {
width: 400px;
border-collapse: collapse;
}
td {
border-top:1px solid green;
padding: 10px 0;
}
.price {
text-align: left;
width: 1%;
white-space: nowrap;
}
<div class="data-right-bottom">
<table>
<tr>
<td>Total products (tax incl.)</td>
<td class="price">
210,00 zł
</td>
</tr>
<tr>
<td>Total shipping (tax incl.)</td>
<td class="price">
12,00 zł
</td>
</tr>
</table>
</div>
Maybe you should change the width of your span to 200px (Span are two inside a "li").

Align span text within li element

Using dataTables, I have a responsive table that produces the following HTML within the child row
<ul data-dtr-index="0" class="dtr-details">
<li data-dtr-index="0" data-dt-row="0" data-dt-column="0">
<span class="dtr-title">Pay No</span>
<span class="dtr-data">999</span>
</li>
<li data-dtr-index="3" data-dt-row="0" data-dt-column="3">
<span class="dtr-title">DOB</span>
<span class="dtr-data">14 Sep 1951</span>
</li>
</ul>
Using CSS, I would like the second span in each li (dtr-data) to have the text aligned to the right. Is this possible in CSS without having to amend the DOM to put the span in a div tag? Ideally I do not want to create my own custom rendere, so to be able to align the span text through CSS only would be ideal
You could use flexbox for this.
This would reset the li display property, which removes the bullet point, so you would need to reintroduce it.
Example:
li {
display: flex;
margin-left: -1em;
}
li:before {
content: '•';
padding-right: .5em;
}
.dtr-data {
margin-left: auto;
}
<ul data-dtr-index="0" class="dtr-details">
<li data-dtr-index="0" data-dt-row="0" data-dt-column="0">
<span class="dtr-title">Pay No</span>
<span class="dtr-data">999</span>
</li>
<li data-dtr-index="3" data-dt-row="0" data-dt-column="3">
<span class="dtr-title">DOB</span>
<span class="dtr-data">14 Sep 1951</span>
</li>
</ul>
You can make the li relative, and the span absolute right:0px. (or use float:right)
li {
position: relative;
}
li span:nth-child(2){
position: absolute;
right: 0px;
}
Method 1
float the nested element in question (.dtr-data).
Code Snippet Demonstration:
.dtr-data {
float: right;
}
li {
max-width: 300px; /* for the sake of demonstration */
clear: both; /* clear floats for good measure */
}
<ul data-dtr-index="0" class="dtr-details">
<li data-dtr-index="0" data-dt-row="0" data-dt-column="0">
<span class="dtr-title">Pay No</span>
<span class="dtr-data">999</span>
</li>
<li data-dtr-index="3" data-dt-row="0" data-dt-column="3">
<span class="dtr-title">DOB</span>
<span class="dtr-data">14 Sep 1951</span>
</li>
</ul>
Method 2
float the nested sibling element (.dtr-title) and declare text-align on containing parent.
Code Snippet Demonstration:
.dtr-title {
float: left;
}
li {
max-width: 300px; /* for the sake of demonstration */
clear: both; /* clear floats for good measure */
text-align: right;
}
<ul data-dtr-index="0" class="dtr-details">
<li data-dtr-index="0" data-dt-row="0" data-dt-column="0">
<span class="dtr-title">Pay No</span>
<span class="dtr-data">999</span>
</li>
<li data-dtr-index="3" data-dt-row="0" data-dt-column="3">
<span class="dtr-title">DOB</span>
<span class="dtr-data">14 Sep 1951</span>
</li>
</ul>
Method 3
Declare flex on the containing parent element and align accordingly with justify-content property.
Code Snippet Demonstration:
li {
max-width: 300px; /* for the sake of demonstration */
display: flex; /* required for following property to apply */
justify-content: space-between; /* to align end-to-end */
}
<ul data-dtr-index="0" class="dtr-details">
<li data-dtr-index="0" data-dt-row="0" data-dt-column="0">
<span class="dtr-title">Pay No</span>
<span class="dtr-data">999</span>
</li>
<li data-dtr-index="3" data-dt-row="0" data-dt-column="3">
<span class="dtr-title">DOB</span>
<span class="dtr-data">14 Sep 1951</span>
</li>
</ul>
A note on flex-box:
Since flex-box has limited to no support for legacy browsers (like I.E) for full browser support and compatibility refer to either one of the aforementioned alternatives.
See browser compatibility:
caniuse.com
flex - CSS | MDN
Method 4
position the nested element in question (.dtr-data) as absolute and offset alignment by declaring a right property value, declare relative positioning on the containing parent element so that the absolutely nested child element is positioned relative to its parent.
note: this solution will most likely require responsive adjustments
Code Snippet Demonstration:
li {
max-width: 300px; /* for the sake of demonstration */
position: relative; /* required */
}
.dtr-data {
position: absolute;
right: 0;
}
<ul data-dtr-index="0" class="dtr-details">
<li data-dtr-index="0" data-dt-row="0" data-dt-column="0">
<span class="dtr-title">Pay No</span>
<span class="dtr-data">999</span>
</li>
<li data-dtr-index="3" data-dt-row="0" data-dt-column="3">
<span class="dtr-title">DOB</span>
<span class="dtr-data">14 Sep 1951</span>
</li>
</ul>

Difficulty in aligning a set of results in an HTML section

I'm using span elements within section containers to build out a set of results that can be dynamically inserted by an external program.
The desired result should look something like this:
However, the result squashes all of the entries together, sticking their containers on the same line:
The title section is very simple, and consists of a section and five spans:
<section class="titleholder">
<span id="htlabelHI">Entry Name</span>
<span id="htlabelHI">Parameter</span>
<span id="htlabelHI">Param in List</span>
<span id="htlabelHI">Param in List2</span>
<span id="htlabelHI">Param in List3</span>
</section>
The css is as follows:
.titleholder {
display: flex;
justify-content: space-around;
text-align:center;
border-top:solid;
border-top-color:lightgray;
border-top-width:thin;
border-bottom:solid;
border-bottom-color:lightgray;
border-bottom-width:thin;
font-family: Verdana;
font-size: 10px;
}
The HTML for the results section is a little more complex:
<section class="results">
<div class="hazardResult">
<span class="EntryName">11</span>
<span class="Param">2</span>
<span class="ParamList1">
<ul>
<li>1</li>
</ul>
</span>
<span class="ParamList2">
<ul>
<li>1</li>
</ul>
</span>
<span class="ParamList3">
<ul>
<li>1</li>
</ul>
</span>
</div>
<div class="hazardResult">
<span class="EntryName">22</span>
<span class="Param">2</span>
<span class="ParamList1">
<ul>
<li>2</li>
</ul>
</span>
<span class="ParamList2">
<ul>
<li>2</li>
</ul>
</span>
<span class="ParamList3">
<ul>
<li>2</li>
</ul>
</span>
</div>
</section>
The CSS is not too dissimilar:
.results {
display: flex;
justify-content: space-around;
padding: 10px 0;
border-bottom:solid;
border-bottom-color:lightgray;
border-bottom-width:thin;
height: 150px;
font-size: 10px;
padding-top: 4px;
padding-left: 20px;
text-align:center;
}
I feel like I need to do something to distinguish the 'div' elements of each hazardResult, however setting the width does little more than move the elements around horizontally. The table has a maximum width of 900px.
I also tried individually setting the widths of each span, but this yielded no results.
What else can I try to even out the spacing? Bear in mind that the height of the div must adapt to the longest list.

How can I use span like table?

I have this HTML structure:
.subject{
width: 50px;
}
<div>
<span class = "subject">Name:</span>
<span class="content">John</span>
</div>
<div>
<span class = "subject">Age:</span>
<span class="content">23</span>
</div>
<div>
<span class="subject">cell phone:</span>
<span class="content">+9400321532</span>
</div>
As you see, those columns aren't in the same line. I want this output:
/*
Name: John
Age: 23
cell phone: +9400321532
How can I do that?
Actually I need a fixed-width for span.subject the size of biggest content length which is cell phone in this case.
Here is my code in reality:
.notifications_list{
margin-top: 1px;
padding-right: 15px;
direction: rtl;
overflow: scroll;
width: 100%;
height: 100%;
}
.notifications_list li{
list-style: none;
}
.notification_date_title{
font-size: 14px;
margin-top: 10px;
}
.note_icon{
}
.note_icon i{
font-size: 20px;
margin: 0px;
}
.note_type{
margin-right: 5px;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet"/>
<div class="notifications_list">
<div class="notification_date_title">امروز +5</div>
<ul>
<li><a><div><span class="note_icon"><i class="fa fa-sort"></i></span><span class="note_type">رای</span><span class="note_date_time">2 ساعت قبل</span></div></a>
</li>
</ul>
<div class="notification_date_title">دیروز +10</div>
<ul>
<li><a><div><span class="note_icon"><i class="fa fa-sort"></i></span><span class="note_type">رای</span><span class="note_date_time">14 ساعت قبل</span></div></a>
</li>
</ul>
<div class="notification_date_title">در هفته گذشته </div>
<ul>
<li><a><div><span class="note_icon"><i class="fa fa-check"></i></span><span class="note_type">تایید جواب</span><span class="note_date_time">2 روز قبل</span></div></a>
</li>
<li><a><div><span class="note_icon"><i class="fa fa-sort"></i></span><span class="note_type">رای</span><span class="note_date_time">3 روز قبل</span></div></a>
</li>
</ul>
</div>
You can use display:table, display:table-row and display:table-cell to make span as table
Use display: table-cell;
.subject {
display: table-cell;
width: 80px;
}
div {
display: table-row;
}
<div>
<span class="subject">Name:</span>
<span class="content">John</span>
</div>
<div>
<span class="subject">Age:</span>
<span class="content">23</span>
</div>
<div>
<span class="subject">cell phone:</span>
<span class="content">+9400321532</span>
</div>
Please try this:
.subject{
width: 82px;
display: table-cell;
float: left;
}
You can make use of display table-row and table-cell to achieve this. Below code you can see that the width of the longest content is taken as the width if not it will take a min-width of 50px;
Hope this is what you are expecting :
.notifications_list{
margin-top: 1px;
padding-right: 15px;
direction: rtl;
overflow: scroll;
width: 100%;
height: 100%;
display: table;
}
.notifications_list div, .notifications_list ul{
display: table-row;
}
.notifications_list li{
list-style: none;
}
.notification_date_title{
font-size: 14px;
margin-top: 10px;
}
.note_icon{
}
.note_icon i{
font-size: 20px;
margin: 0px;
}
.note_type{
margin-right: 5px;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet"/>
<div class="notifications_list">
<div class="notification_date_title">امروز +5</div>
<ul>
<li><a><div><span class="note_icon"><i class="fa fa-sort"></i></span><span class="note_type">رای</span><span class="note_date_time">2 ساعت قبل</span></div></a>
</li>
</ul>
<div class="notification_date_title">دیروز +10</div>
<ul>
<li><a><div><span class="note_icon"><i class="fa fa-sort"></i></span><span class="note_type">رای</span><span class="note_date_time">14 ساعت قبل</span></div></a>
</li>
</ul>
<div class="notification_date_title">در هفته گذشته </div>
<ul>
<li><a><div><span class="note_icon"><i class="fa fa-check"></i></span><span class="note_type">تایید جواب</span><span class="note_date_time">2 روز قبل</span></div></a>
</li>
<li><a><div><span class="note_icon"><i class="fa fa-sort"></i></span><span class="note_type">رای</span><span class="note_date_time">3 روز قبل</span></div></a>
</li>
</ul>
</div>
Try this also:
.subject{
width: 50%;
float:left;
}
.content{width: 50%;
float:right;
}
<div>
<span class = "subject">Name:</span>
<span class="content">John</span>
</div>
<div>
<span class = "subject">Age:</span>
<span class="content">23</span>
</div>
<div>
<span class="subject">cell phone:</span>
<span class="content">+9400321532</span>
</div>

CSS Hover attribute reveal non-div element

I want to be able to use the CSS hover element on each specific element within the div to affect each respective span element aka hovering on "something1" should reveal "text1" and so on.
Is it possible to accomplish this without adding a bunch of div's?
span {
display: none;
}
.something1:hover .text1 {
display: block;
}
<div class="container">
<i class="something1"></i>
<i class="something2"></i>
<i class="something3"></i>
<i class="something4"></i>
<span class="text1">Show 1</span>
<span class="text2">Show 2 </span>
<span class="text3">Show 3</span>
<span class="text4">Show 4</span>
</div>
You could achieve this by using the CSS ~ general sibling selectors like this:
The ~ combinator separates two selectors and matches the second
element only if it is preceded by the first, and both share a common
parent. - Mozilla MDN
span {
display: none;
}
.something1:hover ~ .text1 {
display: block;
}
<div class="container">
<i class="something1">Something 1</i>
<i class="something2"></i>
<i class="something3"></i>
<i class="something4"></i>
<span class="text1">Show 1</span>
<span class="text2">Show 2 </span>
<span class="text3">Show 3</span>
<span class="text4">Show 4</span>
</div>
Select all span tags starting with "textx" class:
span {
display: none;
}
.something1:hover ~ span[class*="text"] {
display: block;
}
<div class="container">
<i class="something1">Something 1</i>
<i class="something2"></i>
<i class="something3"></i>
<i class="something4"></i>
<span class="text1">Show 1</span>
<span class="text2">Show 2 </span>
<span class="text3">Show 3</span>
<span class="text4">Show 4</span>
</div>