Align items baseline for a select - html

I've got a header. In this header there's a title and a picker. The picker is a simple label with a select underneath it. I wish to align the baselines of the title and the text inside the select. If I use align-items: baseline, then the baseline of the title is aligned with the baseline of the label, not the text in the select.
How can I align the baseline of the title with the baseline of the select, instead of the label?
The reproducing code is
<div style="display:flex;align-items:baseline">
<span style="font-size:23px;padding-top:16px">A title</span>
<div>
<div><span>A label</span></div>
<div><select><option>An option</option></select></div>
</div>
</div>

How can I align the baseline of the title with the baseline of the
select, instead of the label?
Based on your markup, what you need is margin-top:auto on your title span.
div.wrap > span { margin-top: auto; }
However, that may not really be an exact baseline because that would depend a lot on the font-size, line-height, padding etc. not only on your title span but also on the select itself.
The snippet below will help to visualize that with the red line showing the baselines:
Snippet:
* { box-sizing: border-box; padding: 0; margin: 0; }
div.wrap { display: flex; margin: 8px; position: relative; }
div.wrap > span { margin-top: auto; margin-right: 4px; font-size: 1.5em; }
div.wrap select { padding: 2px; }
div.wrap::after {
content: ''; display: block;
position: absolute; left: -4px; bottom: 4px;
width: 240px; height: 1px;
background-color: #f00;
}
<div class='wrap'>
<span>A title</span>
<div>
<div><span>A label</span></div>
<div><select><option>An option</option></select></div>
</div>
</div>
Accompanying Fiddle: http://jsfiddle.net/abhitalks/n4z98wvn/
Now why is baseline not aligning with the baseline? It actually does. If you split your label into multiple lines, you'll see that it does align with the baseline of the first line. You could see that clearly by comparing it with flex-start.
As pointed out by #Paulie_D, you could also get the intended result with flex-end. However the same problem as mentioned in my first solution, remains. You could see that clearly by comparing it with a reduced line-height on title.
Below are all the comparisons.
Comparison Snippet:
* { box-sizing: border-box; padding: 0; margin: 0; }
div.wrap { display: flex; align-items: baseline; margin: 16px; }
div.wrap > span { font-size: 23px; border: 1px solid #ddd; }
div.wrap:nth-of-type(2) { align-items: flex-start; }
div.wrap:nth-of-type(3) { align-items: flex-end; }
div.wrap:nth-of-type(4) { align-items: flex-end; }
div.wrap:nth-of-type(4) > span { line-height: 20px; }
<div class="wrap">
<span>A title</span>
<div>
<div>
<span>
A label<br/>which breaks into<br/>lines,
is aligned at baseline with the title.
</span>
</div>
<div><select><option>An option</option></select></div>
</div>
</div>
<div class="wrap">
<span>A title</span>
<div>
<div>
<span>
A label<br/>which breaks into<br/>lines,
is aligned at flex-start with the title.
</span>
</div>
<div><select><option>An option</option></select></div>
</div>
</div>
<div class="wrap">
<span>A title</span>
<div>
<div>
<span>
A label<br/>which breaks into<br/>lines.
The select is mis-aligned with the title.
</span>
</div>
<div><select><option>An option</option></select></div>
</div>
</div>
<div class="wrap">
<span>A title</span>
<div>
<div>
<span>
A label<br/>which breaks into<br/>lines.
The select is aligned neatly with the title.
</span>
</div>
<div><select><option>An option</option></select></div>
</div>
</div>
Comparison Fiddle:http://jsfiddle.net/abhitalks/r8spzk54/1/

Try this:
HTML (no changes; except removed some inline styles and added id)
CSS
#container {
display: flex;
}
#container > div {
display: flex;
flex-direction: column;
}
DEMO: http://jsfiddle.net/c7n0222p/4

Related

How do I vertically center an image with flex when the parent container has align items of baseline?

What I have is the following:
I have an icon on the left that represents a product. Then in H1, I have a product category, and with an h2, I have a product name.
The icon, h1, and h2 are in a parent div with flex and align-items value of baseline. So the text is baseline aligned.
Due to the dynamic nature of how the page title here is retrieved, the icon has to be in this parent div that is baseline aligned.
How can I vertically center the icon within this parent div with flexbox? I know how to accomplish this with vertical alignment and setting line height, but I'd prefer a flexbox approach.
Parent:
.parent {
display: flex;
align-items: baseline;
}
HTML skeleton:
<div class="parent">
<div>Icon</div>
<div>Product Category</div>
<div>Product Name</div>
</div>
Use baseline and center vertical alignment in combination
In the snippet below, I've added a wrapper div to hold the text elements together which get aligned around their baseline. The parent div will align its children vertically center, so that the icon and the text block will be nicely aligned.
.parent {
display: flex;
align-items: center;
font-family: sans-serif;
}
img {
border-radius: 100px;
margin-right: 8px;
}
.text {
display: flex;
align-items: baseline;
}
h3 {
font-size: 24px;
line-height: 32px;
}
p {
font-size: 16px;
line-height: 24px;
}
h3+p {
margin-left: 12px;
}
<div class="parent">
<img src="https://picsum.photos/50" alt="icon" />
<div class="text">
<h3>Product Category</h3>
<p>Product Name</p>
</div>
</div>
You can set align-self:center on the icon if you cannot change the parent div's align-items value to center. Find below an example:
.parent {
display: flex;
align-items: baseline;
gap:1rem; /* added just for readability, you can remove it */
}
.parent div:first-child{
align-self:center;
}
<div class="parent">
<div>Icon</div>
<h1>Product Category</h1>
<h2>Product Name</h2>
</div>

Adding a horizontal line in between texts in HTML

I want to add a horizontal line in HTML between texts like shown in this screenshot. From this code, I get a line but not centered between the texts. How can I achieve this?
What I need is something like: Publication---------------------Method.
My code:
.horizontal{
display: inline-block;
width: 100px;
}
<div class="col-sm-4">
<h4>Publication <hr class="horizontal"/>Method</h4>
</div
You can set flex rules for the h4 tag. Aligns the center rule align-items: center. This example good aligns your line to the center of the words.
.col-sm-4 h4 {
display: inline-flex;
align-items: center;
}
.horizontal{
/*display: inline-block;*/
width: 100px;
margin: 0;
}
<div class="col-sm-4">
<h4>Publication <hr class="horizontal"/>Method</h4>
</div
Another solution is to use the pseudo selector ::after
.horizontal::after{
content: "";
display: inline-block;
border:1px solid black;
margin-left:2px;
margin-bottom: 3px;
width: 100px;
}
<div class="col-sm-4">
<h4>
<span class="horizontal">Publication</span>
Method
</h4>
</div
Add vertical-align property text-top.
vertical-align:text-top;
.horizontal{
display: inline-block;
width: 100px;
vertical-align:text-top;
}
<div class="col-sm-4">
<h4>Publication<hr class="horizontal"/>Method</h4>
</div

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/

targetting only left and right divs, not middle

tried searching for this but haven't found a solution.
I would have a responsive wrapper with multiple (no set number) div's.
So like a gallery!
I would like to only target the left and right divs and remove those(left margin for left div, right margin for the right div) margins so that the divs are against the sides of the screen.
fiddle
.work {
position: relative;
float: left;
width: 20%;
height: 20%;
margin: 5%;
background-color: red;
}
.wrapper_work {
width: 80vw;
height: 100vh;
background-color: black;
}
<div class='wrapper_work'>
<div class='work'>
<p>
this is my portfolio gallery
</p>
</div>
<div class='work'>
<p>
this is my portfolio gallery
</p>
</div>
<div class='work'>
<p>
this is my portfolio gallery
</p>
</div>
<div class='work'>
<p>
this is my portfolio gallery
</p>
</div>
</div>
You can use the pseudo-elements first-child and last-child like this:
.work:first-child {
margin-left: 0;
}
.work:last-child {
margin-right: 0;
}
Updated fiddle: https://jsfiddle.net/sswrL7pq/1/
Margins are probably not the way to go for a truly responsive layout with an arbitrary number of content divs, since you don't know which ones will be at the edges of your layout. There are some different ways of approaching it.
Flex box layouts:
You can style your container similar to this:
display: flex;
justify-content: space-between;
flex-flow: row wrap;
The contents will be arranged in rows, with any extra space placed between the contents, leaving them flush with the edges. Flex box is for newer browsers, IE11+.
Fiddle using flex layout
For older browsers you can take advantage of inline-block and justify to get a similar effect. It isn't quite as clean but works quite well. The key styles are these:
.wrapper {
font-size: 0.1rem;
text-align: justify;
}
.wrapper:after {
content: "";
width: 100%;
display: inline-block;
}
.item {
display: inline-block;
font-size: 1rem;
}
Fiddle using justify layout
you can use CSS 3 flexbox for this:
UPDATE: Included images
body,
p {
margin: 0
}
div {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
background: black
}
p {
min-width:20%;
margin:10px 0;
border: red solid;
}
img {
max-width: 100%;
display:block;
margin:auto
}
<div class='work'>
<p>
<img src="http://dummyimage.com/150x150/fff/000">
</p>
<p>
<img src="http://dummyimage.com/150x150/fff/000">
</p>
<p>
<img src="http://dummyimage.com/150x150/fff/000">
</p>
<p>
<img src="http://dummyimage.com/150x150/fff/000">
</p>
<p>
<img src="http://dummyimage.com/150x150/fff/000">
</p>
<p>
<img src="http://dummyimage.com/150x150/fff/000">
</p>
<p>
<img src="http://dummyimage.com/150x150/fff/000">
</p>
<p>
<img src="http://dummyimage.com/150x150/fff/000">
</p>
</div>
.work:first-child,.work:last-child {
margin: 5% 0;
}

Left aligning absolutely positioned div while maintaining fluidity

I have the following HTML structure:
<div id="outer">
<div id="left">
<div id="leftContainer"><span>bla</span><span>bla</span><span>bla</span><span>bla</span></div>
</div>
<div id="right">
<div class="item"><span>item text 1</span></div>
<div class="item"><span>item text 2</span></div>
<div class="item"><span>item text 3</span></div>
<div class="item"><span>item text 4</span></div>
<div class="item"><span>item text 5</span></div>
<div class="item"><span>item text 6</span></div>
</div>
</div>
With the corresponding styles:
#left, #right {
display: inline-block;
}
.item {
display:inline-block;
padding: 0px 5px;
}
#right {
position: absolute;
/*right:0px;*/ /*this little thing causes my problems*/
text-align:right;
border-color: red;
}
I need the right div to be right aligned. For that I set right:0px; but then the right element overlap the left div. If right:0px; is not set, then the item elements will break on a new line (which is part of my requirements) but the right element will be, obviously, left aligned. See the fiddle, comment/uncomment right:0px; and play with the width of the result panel.
Is the a way of right aligning the right div without overlapping? Floating is currently not a solution.
I'm not entirely clear on how the right div is supposed to behave after the 'collision' point but flexbox does allow for the alignment you wanted without the overlap that seems to be problematical for you.
#outer {
position: relative;
display: flex;
justify-content: space-between;
}
#outer {
position: relative;
display: flex;
justify-content: space-between;
}
div {
border: 1px solid black;
}
#left div span {
margin: 0px 5px;
display: inline-block;
}
.item {
display: inline-block;
padding: 0px 5px;
}
#right {
text-align: right;
border-color: red;
}
<div id="outer">
<div id="left">
<div id="leftContainer">
<span>bla</span>
<span>bla</span>
<span>bla</span>
<span>bla</span>
</div>
</div>
<div id="right">
<div class="item"><span>item text 1</span>
</div>
<div class="item"><span>item text 2</span>
</div>
<div class="item"><span>item text 3</span>
</div>
<div class="item"><span>item text 4</span>
</div>
<div class="item"><span>item text 5</span>
</div>
<div class="item"><span>item text 6</span>
</div>
</div>
</div>
JSFiddle Demo
As i understand you need something like following.
Use display:table-cell will solve your issue:
#left, #right {
display: table-cell;
}
Check Fiddle Here.
Give width: 100%; to .right wills stick right div to right align.
Check Updated Fiddle Here.
Use the flexbox model display: flex for your #right element.
#outer {
overflow: hidden;
}
#left {
float: left;
min-width: 66%;
background-color: #69f;
}
#right {
min-width: 34%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-end;
align-items: stretch;
}
.item {
display: inline-block;
}
See example here: http://jsbin.com/qalilu/3/edit. I've added a min-width constraint, which may be useful.
See browser support: http://caniuse.com/#search=flexbox
And a guide: https://css-tricks.com/snippets/css/a-guide-to-flexbox/