CSS buttons align for all divs except the last one - html

I want to display all buttons aligned to fill full div width, except for the last one. My code is below, but the last div is short and is expanding full width, I don't want this for the last one.
NOTE: The buttons are dynamically generated.
.block {
width: 400px;
display: flex;
flex-wrap: wrap;
}
.button {
background-color: #cec;
border: none;
color: white;
margin: 15px;
padding: 15px;
display: inline-block;
font-size: 16px;
flex: 1 0 auto;
}
<div class="block">
<div class="button">#1 - A LONG TEXT GOES HERE
</div>
<div class="button">#2 - ANOTHER LONG TEXT HERE
</div>
<div class="button">#3 - SOME TEXT HERE
</div>
<div class="button">#4 - SHORT TEXT
</div>
<div class="button">#5 - SHORT
</div>
<div class="button">#6 - SHORT
</div>
</div>

You can have separate classes for the short ones.
.block {
width: 400px;
display: flex;
flex-wrap: wrap;
}
.button {
background-color: #cec;
border: none;
color: white;
margin: 15px;
padding: 15px;
display: inline-block;
font-size: 16px;
flex: 1 0 auto;
}
.short {
max-width: 20vw;
}
<div class="block">
<div class="button">#1 - A LONG TEXT GOES HERE
</div>
<div class="button">#2 - ANOTHER LONG TEXT HERE
</div>
<div class="button">#3 - SOME TEXT HERE
</div>
<div class="button">#4 - SHORT TEXT
</div>
<div class="button short">#5 - SHORT
</div>
<div class="button short">#6 - SHORT
</div>
</div>

You can use :last-child selector, it matches every element that is the last child of its parent.
.button:last-child
Or you can also use nth-last-child(1) because nth-last-child(1) equal to last-child selector
.button:nth-last-child(1)

You can use last-child pseudo-class to target the last element only of you button class.
.button:last-child {
max-width: max-content;
}
Working Example:
.block {
width: 400px;
display: flex;
flex-wrap: wrap;
}
.button {
background-color: #cec;
border: none;
color: white;
margin: 15px;
padding: 15px;
display: inline-block;
font-size: 16px;
flex: 1 0 auto;
}
.button:last-child {
max-width: max-content;
}
<div class="block">
<div class="button">#1 - A LONG TEXT GOES HERE
</div>
<div class="button">#2 - ANOTHER LONG TEXT HERE
</div>
<div class="button">#3 - SOME TEXT HERE
</div>
<div class="button">#4 - SHORT TEXT
</div>
<div class="button">#5 - SHORT
</div>
<div class="button">#6 - SHORT
</div>
</div>

Related

Centering an element [duplicate]

I'm trying to align a top menu which consists of 3 blocks of content.
What I'm trying to achieve is this:
block 1: left aligned
block 2: centered horizontally
block 3: right aligned
If all 3 blocks were the same size, I could use flexbox (as in the snippet), but they're not, so it doesn't produce the output I require.
Instead, flexbox puts equal space between the 3 blocks - resulting in the middle block being aligned off-center.
I was wondering if this could be achieved with flexbox, or if not, another solution. This needs to work robustly in production so a 'Grid' solution is not applicable as there is insufficient support.
.container {
margin: 20px 0;
}
.row {
background-color: lime;
display: flex;
justify-content: space-between;
}
.item {
background-color: blue;
color: #fff;
padding: 16px;
}
<div class="container">
<div class="row">
<div class="item">left, slightly longer</div>
<div class="item">center, this item is much longer</div>
<div class="item">right</div>
</div>
</div>
You can consider flex-grow:1;flex-basis:0% for the left and right elements then use text-align to align content inside. I have added an extra wrapper to keep the background only around the text.
The trick is to calculate the free space by removing only the middle content and split it equally to the left and right element.
.container {
margin: 20px 0;
padding-top:10px;
background:linear-gradient(#000,#000) center/5px 100% no-repeat; /*the center*/
}
.row {
background-color: lime;
display: flex;
color: #fff;
}
.item:not(:nth-child(2)) {
flex-basis: 0%;
flex-grow: 1;
}
.item:last-child {
text-align: right;
}
.item span{
background-color: blue;
display:inline-block;
padding: 16px;
border: 2px solid red;
box-sizing:border-box;
}
<div class="container">
<div class="row">
<div class="item"><span>left, slightly longer</span></div>
<div class="item"><span>center, this item is much longer</span></div>
<div class="item"><span>right</span></div>
</div>
</div>
You can also do the same by keeping the element close. Simply adjust text-align:
.container {
margin: 20px 0;
padding-top: 10px;
background: linear-gradient(#000, #000) center/5px 100% no-repeat; /*the center*/
}
.row {
background-color: lime;
display: flex;
color: #fff;
}
.item:not(:nth-child(2)) {
flex-basis: 0%;
flex-grow: 1;
}
.item:first-child {
text-align: right;
}
.item span {
background-color: blue;
display: inline-block;
padding: 16px;
border: 2px solid red;
box-sizing: border-box;
}
<div class="container">
<div class="row">
<div class="item"><span>left, slightly longer</span></div>
<div class="item"><span>center, this item is much longer</span></div>
<div class="item"><span>right</span></div>
</div>
</div>
I asked what seems to be a very similar question and stack overflow directed me here. The response from #Paolamoralesval inspired me to realise the required effect can be achieved in CSS grid. Now that grid support is pretty much universal I hope that this meets everyone's needs. This solution is I believe fully responsive to window size as well as height and width of the header items as you should see if you resize the window where you view the snippet.
.header {
grid-row: 1;
grid-column: 1;
display: grid;
grid-template-rows: min-content;
grid-template-columns: 1fr 1fr 1fr;
}
.header-left {
justify-self: start;
align-self: center;
text-align: left;
background-color: red;
}
.header-center {
justify-self: center;
align-self: center;
text-align: center;
background-color: green;
}
.header-right {
justify-self: end;
align-self: center;
text-align: right;
background-color: blue;
}
.shrink-kitty {
width: 200px;
}
<html>
<body>
<div class="page">
<div class="header">
<div class="header-left">
<img class="shrink-kitty" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/bb/Kittyply_edit1.jpg/1280px-Kittyply_edit1.jpg"/><br/>
By David Corby<br/>
Edited by: Arad<br/>Image:Kittyplya03042006.JPG<a><br/><a href="https://creativecommons.org/licenses/by/2.5" title="Creative Commons Attribution 2.5">CC BY 2.5, Link
</div>
<div class="header-center">In the middle</div>
<div class="header-right">
Much much much much more on the right hand side</br>
Indeed two lines
</div>
</div>
<div class="body">Body of the page</div>
<div class="footer">At the bottom</div>
</div>
</body>
</html>
can you give flex-grow:1 for the item class and check
.item {
background-color: blue;
color: #fff;
padding: 16px;
flex-grow:1;
}
Hope this is what you are looking for
Alternative using display table (an ancient supported grid).
Quote from https://www.w3schools.com/cssref/pr_tab_table-layout.asp
If no widths are present on the first row, the column widths are divided equally across the table, regardless of content inside the cells
.container {
display: table;
table-layout: fixed
} // would divide cells equally along table's 100% width.
.row {
display: table-row
}
.item {
display: table-cell
}

Shift cells in a row upward while maintaining baseline alignment

Here is a table built with flexboxes. The cells in the row are aligned with the align-items: baseline property.
.data-row {
display: flex;
align-items: baseline;
border-top: 2px solid blue;
border-bottom: 2px solid blue;
font: bold 14px monospace;
min-height: 75px;
}
.data-row + .data-row {
border-top: none;
}
.data-cell {
padding: 30px 15px 15px;
}
.data-cell--text {
flex-grow: 1;
}
<div class="data-row">
<div class="data-cell">1111111</div>
<div class="data-cell data-cell--text">Usually one line is enough</div>
<div class="data-cell">1111111</div>
<div class="data-cell">1111111</div>
</div>
<div class="data-row">
<div class="data-cell">2222222</div>
<div class="data-cell data-cell--text">But sometimes too long text gets into some cell and goes to the next line</div>
<div class="data-cell">2222222</div>
<div class="data-cell">2222222</div>
</div>
When text in a cell has two lines or more, I would like the contents of all the cells in the row to rise closer to the top of the row, while maintaining their baseline alignment.
Can this be achieved?
The question was suggested by user #Kate B on Russian SO.
You can wrap the cells with data in two nested flexbox-blocks:
The inner flexbox aligns the cells with the text to their baseline.
And the outer flexbox aligns the indoor one with the center axis.
If a new line appears in the text of any cell, then this cell increases the height of the inner block, and it rises inside the outer one.
https://codepen.io/glebkema/pen/XWaZNEP?editors=1100
/* Heart of the matter */
.outer-row {
display: flex;
align-items: center;
}
.inner-row {
display: flex;
align-items: baseline;
flex-grow: 1;
}
/* Appearance */
.outer-row {
border-top: 2px solid blue;
border-bottom: 2px solid blue;
font: bold 14px monospace;
min-height: 72px;
}
.outer-row + .outer-row {
border-top: none;
}
.data-cell {
padding: 0 15px;
}
.data-cell--text {
flex-grow: 1;
}
<div class="outer-row">
<div class="inner-row">
<div class="data-cell">1111111</div>
<div class="data-cell data-cell--text">One line</div>
<div class="data-cell">1111111</div>
<div class="data-cell">1111111</div>
</div>
</div>
<div class="outer-row">
<div class="inner-row">
<div class="data-cell">2222222</div>
<div class="data-cell data-cell--text">Two <br>lines</div>
<div class="data-cell">2222222</div>
<div class="data-cell">2222222</div>
</div>
</div>
<div class="outer-row">
<div class="inner-row">
<div class="data-cell">3333333</div>
<div class="data-cell data-cell--text">And <br>three <br>lines</div>
<div class="data-cell">3333333</div>
<div class="data-cell">3333333</div>
</div>
</div>

Align all the fields in a line after applying word-break prop in css

I have 2 spans inside a div:
html:
<div class="main">
<span class="title"> Name</span>
<span class="values">/sys/fs/cgroup/sys/fs/</span>
</div>
here is how it looks:
http://jsfiddle.net/tdrgz1yj/
as you can see the size and volume title getting pushed down when I have long text for Name field. Also I cannot increase the width any more cause in actual app, the Volume field goes out of focus.
Is there a way I can align the Name, Size and Volume fields all in one line even after applying the word-break prop?
Can I make it look something like with css?
Thanks!
Yes. Just add display: flex to the .parent
Example
If you want to move the long text to the same line with the "Name" title, set display: flex to the .main as well.
Example 2
I suggest using span only to wrap inline elements. Instead, use divs :
.parent {
padding: 20px 10px;
margin: 0 0 20px;
display: flex;
width: 100%;
box-sizing: border-box;
}
.parent div {
margin-left: 20px;
}
.main {
flex-basis: 200px;
flex-grow: 1;
flex-shrink: 0;
display: flex;
}
.title {
margin-right: 20px;
display: inline-block;
}
.values {
word-break: break-word;
}
<div class="parent">
<div class="main">
<div class="title">Name:</div>
<div class="values">/sys/fs/cgroup/sys/fs//sys/fs/cgroup/sys/fs//sys/fs/cgroup/sys/fs/</div>
</div>
<div class="main">
<div class="title">Size:</div>
<div class="values">223k</div>
</div>
<div class="main">
<div class="title">Volume:</div>
<div class="values">111</div>
</div>
</div>

How to Center and Right-align on a row with CSS Flex only

Tried many variations like this, but could not get it to work. Here is the last attempt:
.parent {
display: flex;
//justify-content: center;
width: 600px;
background-color: yellow
}
.c {
//flex: 1 1 0;
//text-align: end;
margin-left: auto;
margin-right: auto;
background-color: cyan;
}
.e {
//flex: 1 1 0;
// text-align: end;
background-color: grey;
}
.bs {
background-color: green;
color: white;
width: 70px;
}
with html:
<div class="parent">
<div class="c">
<button class="bs">OK</button>
<button class="bs">Cancel</button>
</div>
<div class="e">
<button class="bs">Help</button>
</div>
</div>
I know how to solve this by placing a 'visibility: hidden' button on the left-hand side and use justify-content with space-between, but I want to learn/know how to do it using CSS only.
Would be grateful for advice.
There is more than one way to do that.
Here with CSS only (no extra markup/hidden element) using a pseudo and make it and each button wrapper take 1/3 each of the total width, by giving them flex-basis: 100% and then the default flex-shrink: 1 will shrink them equally.
.parent {
display: flex;
width: 600px;
background-color: yellow
}
.parent::before, .c, .e {
content: '';
flex-basis: 100%;
}
.c {
background-color: cyan;
text-align: center;
}
.e {
background-color: grey;
text-align: right;
}
.bs {
background-color: green;
color: white;
width: 70px;
}
<div class="parent">
<div class="c">
<button class="bs">OK</button>
<button class="bs">Cancel</button>
</div>
<div class="e">
<button class="bs">Help</button>
</div>
</div>
The above solution is based on the answer I gave here:
How to align groups of buttons on single row with Flex only?
And here is 3 more ways, where the first sample also solve this without any extra markup using absolute positioning
Center and right align flexbox elements
If you want it perfectly aligned, you can add an empty child div and split the three child divs into thirds.
This will work: CodePen Demo
.parent {
display: flex;
background-color: yellow;
}
.parent div {
display: flex;
flex-basis: calc(100% / 3);
}
.c {
justify-content: center;
background-color: cyan;
}
.e {
justify-content: flex-end;
background-color: grey;
}
.bs {
background-color: green;
color: white;
}
<div class="parent">
<div class="a"></div>
<div class="c">
<button class="bs">OK</button>
<button class="bs">Cancel</button>
</div>
<div class="e">
<button class="bs">Help</button>
</div>
</div>
Note: If you want the buttons to be the same size, you can add flex-basis: calc(100% / 3); to your .bs class in the code above.
You might want to add horizontal margin on the center buttons as well.
You can also create an empty child div and call justify-content: space-between on the parent container, but it won't be perfectly aligned: CodePen Demo, or use the snippet below.
.parent {
display: flex;
justify-content: space-between;
background-color: yellow;
}
.bs {
background-color: green;
color: white;
}
<div class="parent">
<div></div>
<div class="c">
<button class="bs">OK</button>
<button class="bs">Cancel</button>
</div>
<div class="e">
<button class="bs">Help</button>
</div>
</div>
.parent00_100perc, .parent01_100perc {
display: flex;
width: 480px;
background-color: yellow;
}
.parent00_100perc::before {
content: '';
flex: 0 0 100%;
}
.parent01_100perc::before {
content: '';
flex: 0 1 100%;
}
.spanflex00 { flex: 0 0 100%;}
.spanflex01 { flex: 0 1 100%;}
.bs {
background-color: green;
color: white;
width: 70px;
}
.itemcenter {
background-color: cyan;
text-align: center;
}
.itemright {
background-color: grey;
text-align: right;
}
<p>Solution is by LGSon. I have just added a bit to verify I understand it by showing the initialisation and shrinkage phases of the solution, i.e.</p>
<p>Phase 1. initialisation that produces three parts of equal size on a single line. From left to right an empty part, a mid part with centred OK and Cancel buttons and a last part with a right-aligned Help button. Size of line 3x480px and is shown.</p>
<p>Phase 2. init & shrinkage that removes equal amount of space on the left and between the mid and right buttons. This leaves the OK and Cancel buttons still centred and shows a 480px wide result>
<p>Phase 1: after initialsation 0 0 100%</p>
<div class="parent00_100perc">
<span class="spanflex00 itemcenter">
<button class="bs">OKAY</button>
<button class="bs">Kancel</button>
</span>
<span class="spanflex00 itemright">
<button class="bs">SOS</button>
</span>
</div>
<p>Phase 2: init and shrinking 0 1 100%</p>
<div class="parent01_100perc">
<span class="spanflex01 itemcenter">
<button class="bs">OK</button>
<button class="bs">Cancel</button>
</span>
<span class="spanflex01 itemright">
<button class="bs">Help</button>
</span>
</div>
<p>This method/solution can create a centred mid-part with one or two edge parts without adding empty divs or hidden elements to one of the edges.

display flex breaking mulitline text box

I had been working on this for some days and reading information about display flex, but I'm still having an issue that I can't fix. I have 3 boxes and they have % width and some px separating each others, something like this
[[first box] [second box] [third box]]
so, to do this I used the nth-of-type(3n+2) in order to get all the middle elements and addind the px separation to both sides
each box has two divs, an image(to the left) and a text, but, when the text has at least two lines, the box get missaligned
[[first box] [second box]
[third box]]
and that's not good. So, playing with the styles if I remove the display:flex and the box were aligned, but the text now is not vertical aligned to the middle -.-
.general-cont {
width: 100%;
text-align: center;
}
.each-cont {
width: 32.5%;
display: inline-block;
margin-top: 6px;
}
.each-cont:nth-of-type(3n+2) {
margin-left: 10px;
margin-right: 10px;
}
.img-cont {
float: left;
height: 48px;
display: flex;
align-items: center;
}
.text-cont {
height: 48px;
overflow: hidden;
align-items: center;
text-align: left;
display: flex;
}
<div class="general-cont">
<div class="each-cont">
<a>
<div class="img-cont">
123
</div>
<div class="text-cont">
456
</div>
</a>
</div>
<div class="each-cont">
<a>
<div class="img-cont">
ABC
</div>
<div class="text-cont">
DEF
</div>
</a>
</div>
<div class="each-cont">
<a>
<div class="img-cont">
QWE
</div>
<div class="text-cont">
ASD
</div>
</a>
</div>
</div>
You're code is a bit of everything. You shouldn't be combining widths, floats etc when you're using flex. Here's a quick example using your code:
.general-cont {
display: flex;
flex-direction: row;
flex-flow: center;
align-items: stretch;
}
.each-cont {
background: #eee;
margin: 0 10px;
padding: 10px;
}
.img-cont {
display: block;
}
http://codepen.io/paulcredmond/pen/rrRvkk
I would advise reading the guide on CSS tricks: https://css-tricks.com/snippets/css/a-guide-to-flexbox/