How to prevent nested elements from wrapping without specifying widths - html

I'm having trouble keeping two nested inline-blocks aligned without specifying widths. I can get the behavior I want using tables but would prefer to use simpler markup. Here's the basic markup:
<div class="error">
<i></i>
<div class="message">Ruh oh</div>
</div>
Here is the basic css:
.error {
border: 2px solid red;
padding: 8px 10px;
}
i {
display: inline-block;
width: 45px;
vertical-align: middle;
}
.message {
display: inline-block;
vertical-align: middle;
}
Here are the requirements:
.error can be any width (usually 100%)
i will be fixed width (usually 45px)
.message will fill the remaining width of the parent .error
both i and .message will be vertically aligned in the middle
.message cannot wrap under i
no javascript
Here is a fiddle showing a good line (short error), a bad line (longer error messages wrap below the i) and a working example with tables (but I don't want tables). Please enlighten me!
http://jsfiddle.net/3m2db1hw/

you need to use display:table to parent Div and display:table-cell to children i.e. <i> and <div>
.error {
border: 2px solid red;
padding: 8px 10px;
display:table;
}
i {
width: 45px;
vertical-align: middle;
display:table-cell !important;
}
.message {
display: table-cell;
vertical-align: middle;
}
here is edited jsfiddle
http://jsfiddle.net/3m2db1hw/1/

Related

Vertically align a varible height text box next to a fixed height image

very common question I know, but I'm still struggling having read similar questions.
I have two divs (containing a variable height text box paragraph and a fixed height image) within a container div, as follows:
<div class="error-row row">
<div class="error-value-col">
<p class="error-value">{{error.message}}</p>
</div>
<a class="cross-link">
<img class="cross" src="/assets/cross.png" alt="close">
</a>
</div>
The accompanying LESS file is:
.error-row {
border: 1px solid #po-yellow;
border-width: 0px 1px 1px 1px;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
position: relative;
margin: 0px;
.error-value-col {
float:left;
vertical-align: middle;
display: inline-block;
width: calc(~'100% - 70px');
.error-value {
font-size: 10px;
padding: 5px;
p {
margin-bottom: 0px;
}
}
}
.cross-link {
padding: 0px;
float: right;
vertical-align: middle;
display: inline-block;
height: 70px;
img.cross {
margin: auto;
width: 70px;
height: 70px;
padding: 28.5px 27.5px 26.5px 27.5px;
color: black;
}
}
}
I've tried several different combinations of settings but none seem to work. I want whatever the element with the smallest height is (out of the image and text box) to centre alongside the taller element.
Thanks all.
EDIT: Clarification...I want the error-value-col and cross-link to be centred on the error-row container. This will of course be sized to the largest element out of the two, which could be either.
I changed approach and use display:table and display:table-cell to obtain desired behaviour. Look at this updated jsFiddle to see if it's acceptable for you (converted LESS in CSS there).
Apart design rules, relevant new ones to LESS code are the following:
.error-row {
...
display:table;
width:100%;
.error-value-col {
...
display:table-cell;
vertical-align:middle;
.error-value {
...
p {
...
}
}
}
.cross-link {
...
display:table-cell;
width:70px;
vertical-align:middle;
img.cross {
...
}
}
}
Please refer to jsFiddle to see all differences including erasing of floating.
ALTERNATIVES:
Vertical aligning is (strangely) an hard topic in CSS, at least if
you don't want to use relatively new Flexbox model.
Generally a very common method is to absolute positioning inner DIV
with top:50% but due to fact that reference point is top-left
corner, then you have to push up it of "half of its height" with a
negative margin-top. This requires to have a fixed height of inner
DIV, in order to set this negative margin to half of it.

Putting an outline around multiple inline elements across line break?

I want to put a colorful outline around a bunch of inline elements. Is there any easy way to make this look right within the flow of the text?
Here's the HTML:
<span>Text Before</span>
<div class="border">
<div>This</div>
<div>is</div>
<div>not</div>
<div>a</div>
<div>public</div>
<div>service</div>
<div>announcement.</div>
</div>
<span>Text After</span>
Here's the CSS:
.border {
display: inline;
background-color: pink;
word-spacing: 10px;
padding: 2px 0 2px 0;
border: solid;
}
.border > div {
display: inline;
font-size: 30px;
background-color: lavender;
}
Screenshot with .border display: inline:
Screenshot with .border display: inline-block:
I want it to look roughly like this (accomplished with a mixture of manual line height, padding, and relative positioning... ugh!):
Basically, inline-block elements do everything right, but they don't break apart between lines as would inline elements. But inline elements collapse their height and have to be manually adjusted. Is there really no way around this?
Try adding a line-height on container div.
.border {
display: inline;
background-color: pink;
word-spacing: 10px;
padding: 2px 0 2px 0;
border: solid;
font-size: 30px;
}
.border > div {
display: inline-block;
margin-bottom: 15px;
background-color: lavender;
}
This is a cop-out answer on my part, but It Works™, at least for my purposes, so I'm using it until something better comes up.
If you're willing to commit the relatively minor crime of putting a span around the content of each inner div and setting the text style for the span instead of the div, you can make each of the divs an inline-block, give the background and border style to each individual div instead of the parent div, set the left/right margin of each div, to 0, and extend the borders of the divs via padding to make it seem like one continuous background rect. If you want an outline, you can use the nth-item selectors and set the borders accordingly.
Here's the revised HTML (also compressed onto one line, to get rid of the spaces between inline-block elements):
<span>Text Before</span>
<div class="border">
<div><span>This</span></div><div><span>is</span></div><div><span>not</span></div><div><span>a</span></div><div><span>public</span></div><div><span>service</span></div><div><span>announcement.</span></div>
</div>
<span>Text After</span>
And here's the revised CSS:
.border {
display: inline;
word-spacing: 0;
}
.border > div {
display: inline-block;
vertical-align: middle;
background-color: pink;
padding: 5px;
margin: 2px 0 2px 0;
border-top-style: solid;
border-bottom-style: solid;
}
.border > div:nth-child(1) {
border-left-style: solid;
}
.border > div:last-child {
border-right-style: solid;
}
.border > div > span {
background-color: lavender;
font-size: 30px;
vertical-align: middle;
}
And here's what it looks like:
This technique breaks down if you want something more complex than a background color with a border, but for my purposes, the benefits — those being far simpler CSS and mostly automatic layout — outweigh the cons.

Vertically Align multi-line text inside a span

I have spent countless hours yesterday and today to figure out how to do this. I cant believe CSS doesn't have an easy way to handle this.
Essentially, I have some text within a span class="name" whose length is not fixed. In certain instances, it can spill over to the next line. How do I vertically align this within my container.
More specifically, how do I vertically align "ABC Father And Sons Company LLC" within my container?
http://jsfiddle.net/D3L8S/
<div class="container">
<span class="name">ABC Father And Sons Company LLC </span>
Address
Hours
More
</div>
css classes
// CSS
.container {
background: #DDEBF0;
padding: 11px;
border: 1px solid #D2D2D2;
width: 380px;
margin-bottom: 10px;
height:18px;
line-height:18px;
display:inline-block;
}
.name {
width:200px;
float:left;
}
.addr, .hours, .more {
width:60px;
float:left;
}
If I add a negative top margin to "name" (margin-top:-8px), I can achieve this but it obviously messes up rendering for XYZ Company LLC
http://jsfiddle.net/FM4dA/
The solution should ideally be Cross-browser compatible (atleast ie8 should support it)
EDIT - I forgot to mention initially that my container width is fixed and cannot be changed.
Here is one way of doing it using inline blocks:
.container {
background: #DDEBF0;
padding: 11px;
border: 1px solid #D2D2D2;
width: 380px;
height: 50px;
line-height: 50px;
margin-bottom: 10px;
display:inline-block;
}
.name {
width:200px;
display: inline-block;
vertical-align: middle;
line-height: 1;
}
.addr, .hours, .more {
display: inline-block;
vertical-align: middle;
line-height: 1;
}
First, make sure to leave enough vertical space for multi-line names, so on .container,
I used height: 50px and line-height: 50px.
However, you need to reset the line-height: 1 (or some suitable value) on the child elements otherwise the interline spacing will not be attractive.
Then, instead of floats, use display: inline-block and vertical-align: middle on the
child elements (.name, .addr, .hours, .more).
See demo at: http://jsfiddle.net/audetwebdesign/Wp84v/
Note: You may not need to specify the width on .addr, .hours, .more, so I let the
widths take on the shrink-to-fit value.
One way to vertically align div's contents is to use the vertical-align css property. But it works only on display:table-cell elements. So, wrap your container into a display:table div, and change the container display to display:table-cell.
Like this: http://jsfiddle.net/D3L8S/2/
Try this, It might help somebody
.name {
width:200px;
float:left;
margin-top:-8px;
word-wrap:break-word;
text-align: center;
}
DEMO
When you want to vertically center multiple lines, put the text into an inline block then pretend that the inline-block was a single line of text.
.container {
background: #DDEBF0;
padding: 11px;
border: 1px solid #D2D2D2;
width: 380px;
margin-bottom: 10px;
height: 18px;
line-height: 18px
display:inline-block;
}
.name {
width:200px;
float:left;
margin-top:-8px;
display: inline-block;
vertical-align: middle;
line-height: 14px;
}
NOTE:
Why you should add the line-height property ?
If you add height to an element , where exactly does the text inside of it lie? That is, if you have a block of text that is font-size: 10px (a theoretical height:10px) inside a container that is 60px where exactly is the text going to end up? Most surely at the top of the container, because the text can only position itself where the text flows, inside a height:10px space. But you can overcome that by using a line-height value the same height as the container, this way the text will take in the vertical-align property and align itself properly.

vertical align is not applied?

I have a Div which has display:table
JSBIN
<div class='wrapper'>
<input type="checkbox" class="b" />
<span class="c" >aaa bbb ccc</span>
</div>
And this css :
.wrapper
{
display: table;
border:solid 1px red;
height:40px;
width:200px;
}
.b
{
border:solid 1px green;
display: table-cell;
vertical-align: middle;
}
.c
{
display: table-cell;
vertical-align: middle;
}
As you can see - Both .b and .c has display: table-cell; vertical-align: middle;
Question
Why does the checkbox is not aligned vertically while the span is ?
NB
I know I can use padding etc to manually alignt the checkbox. But Im looking for the solution with table-cell and vertical align ( which should work)
You need to inherit the height from your table down to your table cells:
.wrapper
{
display: table;
border:solid 1px red;
height:40px;
width:200px;
}
.b
{
border:solid 1px green;
display: table-cell;
vertical-align: middle;
height: inherit;
}
.c
{
display: table-cell;
vertical-align: middle;
height: inherit;
}
See demo at http://jsbin.com/IdOFUmi/23/edit
The reason is that input elements don't quite behave the same as other inline elements. For some reason, setting a height to the table cell fixes the problem.
The best explanation that I can offer is based on my reading about the CSS Table model
and the generation of missing table elements:
http://www.w3.org/TR/CSS2/tables.html#anonymous-boxes
In this case, the input element, being a replaced element, cannot be a table cell. As a result, an anonymous table-cell wrapper is generated internally by the CSS engine.
However, the anonymous table-cell does not seem to recognize the the height of the parent table.
If there is a height specified on the element, then the anonymous table-cell applies it.
The best of evidence for this explanation is that the following CSS also gives the same result:
.b
{
border:solid 1px green;
/* display: table-cell; OMIT THIS */
vertical-align: middle;
height: inherit;
}
without the explicit display: table-cell property, the anonymous element will be drawn and the height property is needed to get the vertical alignment to work.
Try this:
.wrapper
{
display: table-cell;
border:solid 1px red;
height:40px;
width:200px;
vertical-align: middle;
}
.b
{
border:solid 1px green;
}
div span
{
border:solid 1px gray;
}
Working: http://jsbin.com/IdOFUmi/11/edit
You're actually want that .wrapper will behave as table-cell , in this case it will be possible to place its children in the center.

How to center align img wrapped in SPAN tag?

I am trying to center align an image that is wrapped in a <span>, but I am having trouble doing so. I have uploaded my CSS and HTML to jsfiddle: http://jsfiddle.net/7nHhu/1/
I am trying to get the image to center align itself with the content in a "block" style (ie. all text above and below it, not wrapped to the left or right)
Any help would be greatly appreciated.
.imgframe {
border: 1px solid #EAEAEA;
display: inline-block;
margin: 8px;
}
.imgframe img {
border: 1px solid #FFFFFF;
margin: 0;
background: #F6F6F6;
padding: 8px;
-moz-box-shadow: 2px 2px 5px #CCCCCC;
-webkit-box-shadow: 2px 2px 5px #CCCCCC;
}
<span class="imgframe centerimg"><img src="http://i48.tinypic.com/31368e9.jpg" /></span>​
I think it's more appropriate to use text-align for centering text rather than images. You could center an image by setting left and right margin auto.
img {
display: block;
margin-left: auto;
margin-right: auto;
height: auto;
padding-top: 10px; //margin-top doesn't work
}
Demo
Just make image wrapper block level element and text-align:center; it.
FIDDLE
or wrap it in another element if needed;
FIDDLE
In .imgframe, add width: 100%;
Given your requirements, to keep the .imgframe element in-line, to avoid it taking up the full width of the enclosing element, and working without adding wrapping elements to your mark-up, the following works:
body {
text-align: center;
}
body p {
text-align: left;
}
JS Fiddle demo.
This would, probably, be less intrusive if you had the elements from your Fiddle wrapped in a specific, target-able, element; rather than the body, as the method, above, requires you to reset the text-align for all elements contained within the body. So, personally, I'd use:
<div id="contentWrapper">
<p>...</p>
<span class="imgframe">
<img src="..." />
</span>
<p>...</p>
</div>
And:
#contentWrapper {
text-align: center;
}
#contentWrapper p {
text-align: left;
}
Just in order to minimise the amount of work required to tidy up afterwards.
span {position: absolute; top:0; left: 0; width: 100%; text-align: center;}
img {width:yourimagewidth; heigth: width:yourimageheigth}