Align the bottom of a child element with the parent's baseline - css

I would like to vertically align a child element in a flex box (or text box) so that its bottom coincides with the baseline of its siblings.
This happens by default for images:
MDN <img> Element:
<img> has no baseline, so when images are used in an inline formatting context with vertical-align: baseline, the bottom of the image will be placed on the text baseline.
Can I achieve the same effect with a <div> instead of an <img>?
Later edit: I'm attaching a snippet. I want the bottom border of the last child to coincide with the bottom border of the image (the baseline of the rest of the children). I don't want everything aligned to the bottom.
.parent {
display: flex;
align-items: baseline;
}
.child2 {
font-family: monospace;
font-size: 200%;
}
img {
border-bottom: 1px solid red;
}
.child-bottom {
padding: 5px;
background-color: #fdd;
border-bottom: 1px solid red;
}
<div class="parent">
<span>These</span>
<span class="child2">are</span>
<span>baseline</span>
<img src="https://cdn.sstatic.net/Img/ico-binoculars.svg?v=d4dbaac4eec9">
<span>aligned.</span>
<div class="child-bottom">This child's bottom border should be on the baseline of the parent.</div>
</div>
Later edit 2. A picture is a thousand words. Hope it helps clarify what kind of alignment I need. Notice how letters j, p, and q extend below the baseline.

Finally, I found a solution:) It was hidden somewhere in the CSS specification:
The baseline of an 'inline-block' is the baseline of its last line box
in the normal flow, unless it has either no in-flow line boxes or if
its 'overflow' property has a computed value other than 'visible', in
which case the baseline is the bottom margin edge.
This is taken from https://www.w3.org/TR/CSS2/visudet.html#propdef-vertical-align, bottom of the page.
So, in order to move its baseline to the bottom margin edge, you only have to add display: inline-block and overflow: hidden (or anything other than 'visible', eg: 'auto') to the child element:
body {
font-size: 200%;
}
.bottom {
display: inline-block; /* <--- this */
overflow: hidden; /* <--- and this */
width: 10rem;
border: 2px solid orange;
padding: 2rem;
}
<div>
<span>text jklmnopqr</span>
<div class="bottom">div with bottom on the baseline</div>
</div>

So I have not found a good solution for your question, but I give you what I've tried, maybe it will give you some ideas.
Apparently, the baseline alignement with flexbox only align the text content as you want, not the div itself.
.parent {
display: flex;
align-items: last baseline;
}
.child2 {
font-family: monospace;
font-size: 200%;
}
img {
border-bottom: 1px solid red;
}
.child-bottom {
padding: 5px;
background-color: #fdd;
border-bottom: 1px solid red;
}
<div class="parent">
<span>These</span>
<span class="child2">are</span>
<span>baseline</span>
<img src="https://cdn.sstatic.net/Img/ico-binoculars.svg?v=d4dbaac4eec9">
<span>aligned.</span>
<div class="child-bottom">This child's bottom border should be on the baseline of the parent.</div>
</div>
But an empty div will be aligned on baseline ?
.parent {
display: flex;
align-items: baseline;
}
.child2 {
font-family: monospace;
font-size: 200%;
}
img {
border-bottom: 1px solid red;
}
.child-bottom {
padding: 5px;
width:50px;
height:50px;
background-color: #fdd;
border-bottom: 1px solid red;
}
<div class="parent">
<span>These</span>
<span class="child2">are</span>
<span>baseline</span>
<img src="https://cdn.sstatic.net/Img/ico-binoculars.svg?v=d4dbaac4eec9">
<span>aligned.</span>
<div class="child-bottom"></div>
</div>
I have tried solutions with absolute positionning, but you are forced to define the size of the parent, which is not a good solution...
The best solution I found is, I think, to align the text with flexbox, then translate the block with the size of your padding... I hope it helps you a little bit...
.parent {
display: flex;
align-items: last baseline;
}
.child2 {
font-family: monospace;
font-size: 200%;
}
img {
border-bottom: 1px solid red;
}
.child-bottom {
padding: 5px;
background-color: #fdd;
border-bottom: 1px solid red;
transform:translateY(-10px);
}
<div class="parent">
<span>These</span>
<span class="child2">are</span>
<span>baseline</span>
<img src="https://cdn.sstatic.net/Img/ico-binoculars.svg?v=d4dbaac4eec9">
<span>aligned.</span>
<div class="child-bottom">This child's bottom border should be on the baseline of the parent.</div>
</div>
Another solution would be to align everything with flex-end so that every child are aligned at bottom but I guess it is not what you want as you said already.

I created a simplest example.
.parent{
display: inline-flex;
flex-direction: row;
align-items: flex-end
}
.child{
background: red;
color: white;
width: 50px;
height: fit-content
}
<div class='parent'>
<div class='child'>some text</div>
<div class='child'>some more text</div>
<div class='child'>some more more more more more more more more text</div>
</div>

Related

Blockquote styling breaks float-left div?

I have two divs on a page. Div #1 is floated left and contains an image and some text. The text in div #2 wraps around it nicely, as I expect. But when there's a blockquote with some styling in div #2, the styling extends into div #1. This isn't what I want.
I'm sure I'm missing something super basic, but I can't figure out what it is.
In this sample, I don't want the red going into the gray.
.floatl {
float: left;
height: 200px;
width: 100px;
background: #CCCCCC;
opacity: 0.5;
margin-right: 2px;
}
blockquote {
border-bottom: 3px solid red;
border-top: 3px solid red;
}
<div class="floatl"></div>
<div>
<p>This is some text here.</p>
<blockquote>This is a quote.</blockquote>
</div>
I'm looking to either a) get div #2's non-text content to respect div #1 or b) discover another way to float div 1 to the left.
Thanks for your help!
Wrap the divs in a new div and apply display:flex so it will become the flexbox container.
.new-wrapper {
display: flex;
}
Your main content, which is now a flex item along with the .float1 div, will want to shrink up. I gave the content div a class and told it to grow to fill the rest of the flex container:
.main-content {
flex-grow: 1;
}
Remove the float and now you are good.
.new-wrapper {
display: flex;
}
.floatl {
height: 200px;
width: 100px;
background: #CCCCCC;
opacity: 0.5;
margin-right: 2px;
}
.main-content {
flex-grow: 1;
}
blockquote {
border-bottom: 3px solid red;
border-top: 3px solid red;
}
<div class="new-wrapper">
<div class="floatl"></div>
<div class="main-content">
<p>This is some text here.</p>
<blockquote>This is a quote.</blockquote>
</div>
</div>

How to add a <span> in a middle of a sentence when using a flexbox?

Given a flex container that contains a sentence, I'd like to wrap one of the words with a <span> for some additional styling. Example:
div {
display: flex;
border: 1px solid black;
width: 190px;
flex-wrap: wrap;
}
span {
color: red;
}
<div>
This is <span>not</span> a very long sentence.
</div>
As you can see, the sentence breaks after the <span>.
The desired outcome is:
div {
display: flex;
border: 1px solid black;
width: 190px;
flex-wrap: wrap;
white-space: pre;
}
.red {
color: red;
}
<div>
<span>This </span>
<span>is </span>
<span class="red">not </span>
<span>a </span>
<span>very </span>
<span>long </span>
<span>sentence.</span>
</div>
How would you solve this?
Try with display: inline-block;
div {
display: inline-block;
border: 1px solid black;
width: 190px;
flex-wrap: wrap;
}
span {
color: red;
}
<div>
This is <span>not</span> a very long sentence.
</div>
Wrap the contents of the flexbox div within a span
div {
display: flex;
border: 1px solid black;
width: 190px;
}
span#inner {
color: red;
}
<div>
<span>This is <span id="inner">not</span> a very long sentence</span>
</div>
You could wrap the text in a <p> so that the span inherits the properties of paragraph besides it being the right way of handling the HTML semantically. Correct me if I am wrong but it adds accessibility to it.
div {
display: flex;
border: 1px solid black;
width: 190px;
flex-wrap: wrap;
}
span {
color: red;
}
<div>
<p>This is <span>not</span> a very long sentence.</p>
</div>
Option 2: Don't wrap the div in flex. Use inline-block
div {
display: inline-block;
border: 1px solid black;
width: 190px;
flex-wrap: wrap;
}
span {
color: red;
}
<div>
<p>This is <span>not</span> a very long sentence.</p>
</div>
Let the div do what it naturally does, so just define a width and the desired border.
There's no reason to give the div any display property, especially not display: flex.
div {
border: 1px solid black;
width: 190px;
}
span {
color: red;
}
<div>
This is <span>not</span> a very long sentence.
</div>
The accepted answer works, but doesn't really explain the question.
For spacing, all inline elements are interpreted as normal texts in each tag.
div {
border: 1px solid black;
width: 190px;
}
span {
color: red;
}
<div>
This is <span>not</span> a very long sentence.
</div>
It's like that this div element has three "Text Nodes" and the word "not" is just separated from the rest of the text in order to have control over it (in CSS, JS).
The default div (with display: block) treats these "three nodes" like one line text in the matter of spacing, which is the action of removing all white-spaces and leaving only one. So the (single) space between the words is and <span> and between the words </span> and a very are preserved like a normal white-space in a sentence.
But when you set the div's display to flex, Each text node acts as a column for this new flex-box and all the space between them is removed.
div {
border: 1px solid black;
width: 190px;
display: flex;
}
span {
color: red;
}
<div>
This is <span>not</span> a very long sentence.
</div>
In my opinion it's usually not wise to put text nodes directly inside flex parents.

CSS - Dynamic padding to expand divs to fill a dynamic width

So I have a variable number of elements in a div that has a variable width. The elements inside have a fixed space between them, 5px, but each one needs to expand to fill the full width of the space of the outer div with padding, so the text can be centerized.
Example:
.button-container{
width: 100%;
height: 50px;
}
.button-container .button{
min-width: 75px;
display: inline-block;
text-align: center;
border: 1px solid #FF0000;
}
.button-container .button + .button-container .button{
margin-left: 5px;
}
<div class='button-container'>
<div class='button'>B1</div>
<div class='button'>B2</div>
<div class='button'>B3</div>
<div class='button'>B4</div>
</div>
So how can I make the padding inside of the button class elements have a dynamic left and right padding to fill the space of the button-container class div?
Ideally, the solution will be a CSS only solution, as I don't want to have jQuery to do the spacing.
CSS tables would work here.
.button-container {
width: 100%;
height: 50px;
display: table;
border-collapse: separate;
border-spacing: 5px;
}
.button-container .button {
display: table-cell;
text-align: center;
border: 1px solid #FF0000;
vertical-align: middle;
}
<div class='button-container'>
<div class='button'>B1</div>
<div class='button'>B2</div>
<div class='button'>B3</div>
<div class='button'>B4</div>
</div>
You can use flexbox:
.button-container {
display: flex; /* Magic begins */
}
.button-container > .button {
flex: 1; /* Distribute the width equally */
text-align: center;
margin-left: 5px;
border: 1px solid #FF0000;
}
.button-container > .button:first-child {
margin-left: 0;
}
<div class='button-container'>
<div class='button'>B1</div>
<div class='button'>B2</div>
<div class='button'>B3</div>
<div class='button'>B4</div>
</div>

CSS: inline-block vs inline text

I want my block to be set by line-height (just like i do with text). As i know i should use display: inline-block in this case, but this doesn't work for me. Why?
HTML:
<div class="block">
<div></div>
</div>
<div class="block">
test
</div>
CSS:
.block {
line-height: 50px;
height: 50px;
width: 50px;
border: 1px solid black;
}
.block div {
height: 40px;
width: 28px;
background-color: #f0f;
display: inline-block;
}
Live demo: jsFiddle
hi now add your div aertical-align middle in your css
.block div {
vertical-align: middle;
}
Demo
--------------------------------------------
now if you want to center this box than add text-align center as like this
.block {
text-align: center;
}
Demo
i guess you are trying to center the purple block vertical?
in that case your mixing thing up:
a <div> is a block-level element, where text is not. so if you say line-height, you specify text-alignment of the content for that element, not positioning of a block element, to solve the centering of that purple block, use padding or margin:
.block div {
height: 40px;/* 50 - 40 = 10pixel/2 = 5px space */
width: 28px;
background-color: #f0f;
margin-top: 5px;
}
Demo over here jsFiddle

padding-top to h1 in vertically align div

i have a div that has a specific height and the content inside adjusts according to height VERTICALLY now what i did is i added the property display-table; to the parent div and display: table-cell;vertical-align: middle; to the child div now what happens is my div is vertically aligned and looking good but the h1 inside the child i not exactly as centered aligned as the button i figured adding some padding top or margin top might solve the issue but it is not accepting either of these here's my code
html
<div class="all-smiles" id="parent">
<div id="child">
<div class="container" align="center">
<div class="row">
<h1>All Smiles Welcome</h1>
<button>BOOK AN APPOINTMENT</button>
</div>
</div>
</div>
</div>
css
#parent {
display: table;
width: 100%;
height: 250px;
}
.all-smiles {
background-color: #b7181c;
}
.all-smiles h1 {
color: white;
display: inline;
margin-right: 3%;
}
.all-smiles button {
padding: 12px;
background: 0;
color: white;
border: 1px solid #fff;
text-decoration: none;
font-family: young;
}
#child {
display: table-cell;
vertical-align: middle;
}
FIDDLE
You need to specify these two:
Vertical Alignment as middle
Line height and 1
Code:
.all-smiles h1 {
color: white;
display: inline;
margin-right: 3%;
vertical-align: middle;
line-height: 1;
}
Preview
Fiddle: https://jsfiddle.net/wd3sr2xv/

Resources