Pre History
I am building html form, with elements having multiple options ...., but instead of showing it as dropdown, i would like to show them as buttons without using any js, I removed buttons with label pointing to input checkbox.
Problem
I need label (or anchor or div) tag behave exactly like button tag without any extra wrapper tags, I googled all variation doesn't provide same result as native tag button.
<button class="button">
Text
<div>Small Text</div>
</button>
Solutions not work
line-height, padding does not provide same functionality, because button height/width and text length may vary. I tried special webkit style -webkit-appearance: button; no changes.
Mustery Flex
I tried flex
.button {
flex-wrap: wrap;
align-items: center;
justify-content: center;
display: inline-flex;
}
<div class="button">
Text
<div>Small Text</div>
</div>
but child div inside button not breaking/warping to new line.
p.s Environment tested, Google Chrome, Safari
I found solution using flex with flex-direction: column; so text and div treats like column items, here is code
label.button {
flex-direction: column;
justify-content: center; /* <-- actual veertical align */
display: inline-flex;
text-align:center;
}
JS Fiddle Demo
Does this does the job ?
div.button {
align-items: center;
text-align: center;
display: inline-block;
border: 1px solid black;
}
div.button div {
clear: both;
}
<div class="button">
Text
<div>Small Text</div>
</div>
Ghost element trick looks work well.
.wrap {
text-align: center;
background: #ededed;
margin: 20px;
}
.wrap:before {
content: '\200B';
display: inline-block;
height: 100%;
vertical-align: middle;
}
.centered-guy {
display: inline-block;
vertical-align: middle;
width: 300px;
padding: 10px 15px;
border: #777 dotted 2px;
background: #666;
color: #fff;
}
<div class="wrap" style="height: 512px;">
<div class="centered-guy">
<h1>Some text</h1>
<p>Bool!<br>Look at me, mama!</p>
</div>
</div>
Related
How can I create icons with text below them in a row, with css?
I currently have this:
<div class="icon-stats">
<div class="video-stats-holder">
<span class="icon-video-stat"></span><span class="video-stat-descr">12</span>
</div>
<div class="playlist-stats-holder">
<span class="icon-playlist-stat"></span><span class="playlist-stat-descr" >5</span>
</div>
</div>
with my css:
.icon-stats {
max-width: 160px;
padding-top: 30px;
}
.video-stats-holder, .playlist-stats-holder {
display: flex;
align-items: center;
flex-direction: column;
}
.icon-video-stat, .icon-playlist-stat {
padding: 5px;
height: 64px;
width: 64px;
}
.icon-video-stat {
background: url('/css/icons/video-stats.png');
}
.icon-playlist-stat {
background: url('/css/icons/playlist-stats.png');
}
The code above is based on this answer, but that doesn't completely work for me, it seems.
The icon and text appear now in one column, all below each other.
I want the icons next to each other, (with the text centered below it).
You can give .icon-stats class a display property of flex display:flex
Just update your CSS with the following code
.icon-stats {
max-width: 160px;
padding-top: 30px;
display: flex;
}
I have HTML code that goes like this:
.container a.source {
align-self: flex-start;
}
.container p {
display: flex;
flex-direction: column;
}
<div class="container">
<p>
looooooooooong
mediumish
short
Text here link with no class more text.
</p>
</div>
By default, links will be displayed inline, but I want them to start from a new line.
I can easily place a <br> tag after each link but would prefer not to.
display: block would make the links take up the whole width.
inline-block would display links next to each other which is not what I want.
display: table-row. It's a better option than display: block, but different shorter links would take the same length as the longest of them.
CSS display: table-cell looks great, but not when there is more than one link since they will be displayed next to each other.
Is there a way to force each link with a class to:
Start from a new line.
Have individual length.
Do this without altering HTML?
A solution was offered:
a {
align-self: flex-start
}
p {
display: flex;
flex-direction: column;
}
The links are displayed just as I want them to. Problem is that other links are displayed in a similar manner, which is not desired.
Flexbox can do that:
a {
background: pink;
align-self: flex-start
}
a:hover {
background: green;
}
p {
display: flex;
flex-direction: column;
}
<p>
link long variety
link
link Text here
</p>
This is your goal?
.link-list {
display: flex;
flex-direction: column;
};
<p class="link-list">
<a>link</a>
<a>link</a>
<a>link</a>
Text here
</p>
You could use block and set a max-with to avoid using the whole width.
a{
display: block;
max-width: 100px;
}
<a>link</a>
<a>link</a>
<a>link</a>
<p>Text here</p>
Another approach (a very old one, from days loooooooooong before CSS Flexbox and CSS Grid arrived on the scene...):
Combine the following:
display: inline-block
float: left
clear: left
Working Example:
a {
display: inline-block;
float: left;
clear: left;
margin-bottom: 2px;
padding: 6px;
color: rgb(255, 255, 255);
background-color: rgb(255, 0, 0);
border-radius: 4px;
}
<p>
<a>loooooooooongLink</a>
<a>mediumLink</a>
<a>shorty</a>
</p>
I've had a bit of an issue with some flex containers. They're a label and an input in a flex container. Unfortunately, if I change the height of the container from auto, the contents cease aligning - the label's text remains at the start of the flexbox, but the input's text follows the middle. I've written a MWE to demonstrate.
label, input {
border-style: solid;
border-width: 2px;
border-color: red;
background-color: black;
}
.stretch {
display:flex;
height: 4em;
}
.baseline {
display: flex;
height: 4em;
align-content: baseline;
}
.flex-innards {
display: flex;
height: 4em;
align-content: stretch;
}
.flex-innards * {
display: flex;
align-items: center;
}
.flex-innards-start {
display: flex;
height: 4em;
align-content: stretch;
}
.flex-innards-start * {
display: flex;
align-items: flex-start;
}
.short {
height: auto;
}
<div class="stretch">
<label>Stretch alignment</label>
<input value=":("></input>
</div>
<div class="baseline">
<label>How about baseline?</label>
<input value=">:("></input>
</div>
<div class="flex-innards">
<label>Flexing the children kinda works</label>
<input value=":o"></input>
</div>
<div class="flex-innards-start">
<label>But only if they're centered</label>
<input value=":("></input>
</div>
<div class="field short">
<label>Deceptive stretch</label>
<input value=":S"></input>
</div>
https://jsbin.com/nulobolulo/edit?html,css,output.
I've managed to make them vertically centered together in the third box there (using How to vertically align and stretch content using CSS flexbox), but I'd like to have them both have their text aligned to flex-start, as well as filling the complete height of their container.
If possible, I'd like to avoid adding extra elements to the HTML. Thank you.
I think the only way to address this problem with CSS uses the padding property.
input {
padding-bottom: 40px;
}
label,
input {
border-style: solid;
border-width: 2px;
border-color: red;
}
.stretch {
display: flex;
height: 4em;
}
<div class="stretch">
<label>Stretch alignment</label>
<input value=":(">
</div>
I'm basically trying to get the baseline of the value to align with the baseline of the bottom unit instead of the first as it's happening in my code below.
I can get it to work if I ditch flexbox altogether but I need it for responsiveness.
The canonical advice seems to be to wrap flex items in inline-block but, as you can see from that codepen, it doesn't seem to work for me.
Here's the codepen where I've been trying stuff: https://codepen.io/jskrt/pen/OJyXxyv
.value_and_unit {
display: flex;
flex-flow: row nowrap;
justify-content: flex-start;
align-items: baseline;
}
.value {
line-height: 1;
font-size: 120px;
margin-right: 10px;
}
.unit_container {
display: flex;
flex-flow: column nowrap;
justify-content: flex-end;
align-items: center;
}
.divider {
width: 100%;
}
.inline-block {
display: inline-block;
}
<div class="value_and_unit">
<span class="value">
340
</span>
<div class="unit_container">
<span class="unit">
m
</span>
<hr class="divider" />
<span class="unit">
s
</span>
</div>
</div>
Try the following:
.value_and_unit {
display: flex;
/* flex-flow: row nowrap; */
/* justify-content: flex-start; */
/* align-items: baseline; */
}
.value {
font-size: 120px;
margin-right: 10px;
line-height: 1;
}
Tell me if this is the desired effect, and if not, tell me what is the problem, so I have a clue to follow. Good luck!
EDIT: Replace the <h1> tag with <div> because browsers add line-height, margin and other properties to it by default! Style the item as desired, by adding bold by yourself. Keep in mind that h1 is a semantic tag with high weight and should not be used when not required!!!
EDIT2: I forgot to mention that I worked with the code in real environment and not in the code pen and everything seemed well if I understood your problem correctly. Try it yourself in real server too, if there is a problem with the codepen.
If the .value element will contain numbers only, then you can probably get away with a simple adjustment to the line-height. Make it bit smaller, so that the line box shrinks-to-fit the font height.
.value_and_unit {
display: flex;
border: 1px solid red; /* demo */
}
.value {
line-height: .75; /* key adjustment */
font-size: 120px;
margin-right: 10px;
}
.unit_container {
display: flex;
flex-flow: column nowrap;
justify-content: flex-end;
align-items: center;
}
.divider {
width: 100%;
}
<div class="value_and_unit">
<span class="value">340</span>
<div class="unit_container">
<span class="unit">m</span>
<hr class="divider" />
<span class="unit">s</span>
</div>
</div>
However, this method won't work if the .value element contains random letters, because the extra space above and below the numbers exists to accommodate descenders and ascenders.
In such case, you would need to try another method. align-items: flex-end would work (i.e. the visual baselines would be aligned), but the units would align below the numbers in this case.
.value_and_unit {
display: flex;
align-items: flex-end;
border: 1px solid red;
padding: 5px;
}
.value {
font-size: 120px;
margin-right: 10px;
border: 1px dashed blue;
}
.unit_container {
display: flex;
flex-flow: column nowrap;
align-items: center;
border: 1px dashed blue;
}
.divider {
width: 100%;
}
<div class="value_and_unit">
<span class="value">340jÁ </span>
<div class="unit_container">
<span class="unit">m</span>
<hr class="divider" />
<span class="unit">s</span>
</div>
</div>
So, because you want the "s" baseline aligned with the numbers' baseline, you're not actually seeking baseline alignment (because the true baseline of the larger box is under the "j"). You want an arbitrary alignment, so an adjustment to the line-height may be appropriate in this case.
Try to make the align-items value to end. It is like this
align-items: end;
I tried to vertically centralize plain text inside a flex box element.
I decided to use property display:table-cell with vertical-align: middle. But it doesn't seem to work properly in flexbox elements.
How can I centralize it vertically, ideally without using a wrapper or positioning, and while still truncating long text with ellipses?
.container {
width: 400px;
height: 400px;
font-weight: 700;
border: 1px solid #d9d9d9;
display: flex;
flex-direction: column;
}
.item {
display: table-cell;
vertical-align: middle;
flex: 1 1;
background-color: cyan;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.item:nth-of-type(2n) {
background-color: aliceblue;
}
<div class="container">
<div class="item">Hello, I'm very very long string! Hello, I'm very very long string!</div>
<div class="item">Hello</div>
<div class="item">Hello</div>
<div class="item">Hello</div>
</div>
View On CodePen
One solution is to define each flex item as its own flex container in order to vertically center its contents with align-items:center. To keep text-overflow working, add a child element to each flex item, which can then be truncated with ellipses.
I can't offer a succinct explanation as to why text-overflow doesn't work with display:flex, and neither can David Wesst. In his words:
It turns out that there really isn't a clean way to do this. If you're wondering how I came to that conclusion you can stop because I didn't. Those responsible for the specification did, and you can read the full conversation that started with a Mozilla bug report and leads to a whole mail group discussion about why it should (or, in this case, should not) be implemented as part of the spec.
Here's a working example:
.container {
width: 400px;
height: 400px;
font-weight: 700;
border: 1px solid #d9d9d9;
display: flex;
flex-direction: column;
}
.item {
display: flex;
align-items: center;
flex: 1;
background-color: cyan;
}
.item span {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.item:nth-of-type(2n) {
background-color: aliceblue;
}
<div class="container">
<div class="item"><span>Hello, I'm very very long string! Hello, I'm very very long string!</span></div>
<div class="item"><span>Hello</span></div>
<div class="item"><span>Hello</span></div>
<div class="item"><span>Hello</span></div>
</div>
Also see:
Setting ellipsis on text from a flex container
When you make an element a flex container (with display: flex or display: inline-flex), all in-flow children become flex items.
All flex items have their display value controlled by the container. It doesn't matter what you specify, the container overrides it.
So when you give a flex item display: table-cell, the browser ignores it. Here's what it looks like in Chrome Dev Tools:
Style Tab
Computed Tab
A flex container "blockifies" flex items, causing them to assume many qualities of block-level elements (source).
But the vertical-align property applies only to inline-level and table-cell elements (source).
That's why it doesn't work.
Regardless, vertical-align, even if it worked, is a totally unnecessary hack in this case. There are flex properties designed for aligning content in flex items.
.container {
width: 500px;
height: 500px;
font-weight: 700;
border: 1px solid #d9d9d9;
display: flex;
flex-direction: column;
}
.item {
flex: 1 1;
display: flex;
justify-content: center; /* horizontal alignment, in this case */
align-items: center; /* vertical alignment, in this case */
background-color: cyan;
}
.item:nth-of-type(2n) {
background-color: aliceblue;
}
<div class="container">
<div class="item">Hello</div>
<div class="item">Hello</div>
<div class="item">Hello</div>
<div class="item">Hello</div>
</div>
Related posts:
How to vertically align text inside a flexbox?
Setting ellipsis on text from a flex container
Blockquote ...float, clear and vertical-align have no effect on a flex item.
according to https://css-tricks.com/snippets/css/a-guide-to-flexbox/
See How to vertically align text inside a flexbox? for a possible solution.
You have to define those items also as flex containers, using the following CSS for them (no table-cell display...):
display: flex;
flex-direction: column;
justify-content: center;
.container {
width: 400px;
height: 400px;
font-weight: 700;
border: 1px solid #d9d9d9;
display: flex;
flex-direction: column;
}
.item {
display: flex;
flex-direction: column;
justify-content: center;
flex: 1 1;
background-color: cyan;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.item:nth-of-type(2n) {
background-color: aliceblue;
}
<div class="container">
<div class="item">Hello, I'm very very long string! Hello, I'm very very long string!</div>
<div class="item">Hello</div>
<div class="item">Hello</div>
<div class="item">Hello</div>
</div>