Strange behavior with table-cell layout and empty div - html

I just stumbled over a very strange behavior with a layout which uses the table-cell css property. I tried the following code in current FF, Safari and Chrome. The behavior is the same everywhere.
My questions is whether someone knows why this happens. Is it a browser bug or a defined behavior? I found this question which has a hint on how to solve the problem, but I would rather like to know why this is happening in the first place. I think other people would also like to know.
Problem: If I comment in the in the second table-cell, everything is fine. If, however the div stays empty the content of the two other cells has something like an "offset-top". This offset has the same dimension as the height of the middle cell. I.e. the content of the outer cells is shifted to the bottom. I added two screenshot div_not_empty.png and div_empty.png.
thanks
Update
I forgot the screenshots. Here they are:
Code:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Strange behavior with table-cell formatting</title>
<style type="text/css" media="screen">
#table {
display: table;
background: #efefef;
}
div.cell {
display: table-cell;
}
#c1 div.content {
width: 200px;
}
#c2 {
border-left: 2px solid #ccc;
}
#c2 div.content {
height: 150px;
width: 150px;
background: #aaa;
vertical-align: bottom;
}
#c3 {
width: 200px;
border-left: 2px solid #ccc;
}
</style>
</head>
<body>
<div id="table">
<form id="c1" class="cell">
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipisicing
elit, sed do eiusmod tempor incididunt ut.
</div>
</form>
<div id="c2" class="cell">
<div class="content">
<!-- -->
</div>
</div>
<div id="c3" class="cell">
<div class="content">
Dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure
dolor in reprehenderit.
</div>
</div>
</div>
</body>
</html>

It's got to do with the way that vertical-align: bottom is calculated - see the mdc docs, when applied to table cells, bottom "Aligns the bottom padding edge of the cell with the bottom of the row".
When the table cell has no content, padding is not drawn in the box (i.e. when when 0, if there is content, the browser calculates where the padding would be).
With a element, there is content to use as the basis for the alignment; without it you'll notice the browsers line the bottom of the element itself up with the bottom of the first line of content in the other elements.
re: the question you link to, using vertical-align: top works because the layout is calculated based on the top of the block elements, not the content they contain.
A simple fix for the issue is to add padding to the .content divs in your stylesheet, which then causes them to render as if they have content, meaning you don't need to have 's in your code when there's nothing to display:
div.content {
height: 150px;
padding-bottom: 1px;
}
Try this and you'll see it behaves as you expect.
So; not really a browser bug, as the browser is trying to calculate the position based on the content (or, bottom of padding) of an element, and the element has no content. Possibly an unintended side-effect of the spec in this case though.
On a related note, your css rule div.cell isn't matching the first 'cell' which is a form element. It's working because all elements inside a display: table element have display: table-cell applied automatically, but not the best.

Related

How do I make a child div as wide as its dynamically sized grandparent?

I am trying to make a child div appear as wide as its grandparent. My desired effect is similar to the one desired in this question, but with the key difference that the grandparent is not the width of the viewport; instead, it is determined dynamically.
<div class="outer">
<div class="content">
<div class="inner">
</div>
</div>
</div>
In my example below, the green .inner div should appear as wide as the .outer div, whose width is dynamically calculated by the flexbox <body>. Ideally the text wrapping would be the same in the .inner and .content divs. I also want the inner to remain in the document flow, or at least appear to be. The inner div is generated by a Markdown converter, so it's not easy to edit the content/inner relationship.
How do I make the inner div appear as wide as its grandparent? I would strongly prefer a pure-CSS solution.
Here are some things that do not work:
Absolutely positioned .inner div (with left:0; right:0;), with the .outer div marked position: relative to make it the containing box. This almost works but it removes the inner element from the flow.
Setting the inner element's width to 100vw and shifting it around. There's no way to access the result of the automatic width calculation, so in addition to being very hard to reason about, this also causes problems when scrollbars appear.
body {
display: flex;
}
.sidebar {
flex: initial;
width: 9rem;
text-align: center;
background: lightblue;
}
.outer {
flex: 1;
}
.content {
max-width: 15rem;
margin-left: 1rem;
margin-right: 1rem;
padding-left: 1rem;
padding-right: 1rem;
}
.inner {
background: lightgreen;
padding-top: 1rem;
padding-bottom: 1rem;
margin-top: 1rem;
margin-bottom: 1rem;
}
<html>
<body>
<div class="sidebar">sidebar</div>
<div class="outer">
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
<div class="inner">
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
</body>
</html>
This is what display: contents does (more info), but browser support is a bit limited. You may be able to get by with fallback styles for non-supporting browsers (using #supports in your CSS), or with this JS polyfill.
Not sure if I understood your question correct, but adding
margin-left: -1rem;
margin-right: -1rem;
padding-left: 1rem;
padding-right: 1rem;
to the .inner class would solve it, wouldn't it?

Same distance from image to text (padding) when resizing (responsive)

First post on stackoverflow, and i hope you guys are able to help me out.
I have a picture, which is resized responsively, but i keep getting some annoying spacing because of my relative padding with 0.5em. This means i have two scenarios according to my window size. 1: The spacing fits, like this, or 2: I an annoying space in the bottom because of the em padding like this.
So my question is, is there a way, to make sure that the distance from image to right text is the same as distance from image to bottom text? I wouldn't mind, if my picture expanded a bit in height, so the distance's always the same.
I've tried with some different divs, and some different approaches in terms of responsiveness, but i can't get anything to work. Hope you guys can help me out.
HTML:
<div class="panel-body">
<div class="img-exp">
<img src="http://placehold.it/100x100">
</div>
<div class="text-exp">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</p>
</div>
</div>
CSS:
.panel-body {
text-align: justify;
background-color:black;
padding:0.5em;
}
.img-exp {
position: relative;
float: left;
width:45%;
overflow:auto;
height:auto;
padding:0 0.5em 0.5em 0; /*top right bottom left */
}
.img-exp img{
max-width: 100%;
height: auto;
/*
height:auto;
max-width: 100%;*/
}
Thanks in advance.
It is produced because you have padding-bottom: 0.5em, so when you see the second example and if a line doesn't fits completely you will have that gap.
You need to make perfect calculations with the font-size, the line-height and the number of lines that the height of the image can fit. For example:
Imagine that your image is 100x100, your font-size is 10px and your line-height is 15px. 100 / 15 = 6.66666666666 so it fits 6 lines of text and the last line will occupy 0.6 lines (60% of a normal line). To avoid this, you need to make another calculation.
If in this same calculation, you change the line-height to 20px, you'll obtain: 100 / 20 = 5, it means, 5 exactly lines and nothing in the bottom, so the text doesn't make a gap with your image.

An h3 element is not filling a div with a horizontal scroll bar correctly

Here are two snap shots of the problem.
See how the yellow background of the h3 is cut off?
Here is a jsfiddle
Here is the code:
<style>
.OutputDiv {
background-color: lightcyan;
overflow: auto;
border: solid 2px black;
width: 500px;
}
h3 {
margin-top: 0px;
background-color: yellow;
}
</style>
<div class="OutputDiv">
<h3>My Title is Here</h3>
<pre>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
</pre>
</div>
I know I could probably add another div with a background color to contain the h3, but the h3 is a block level element.
Any ideas?
Even though <pre> is a block level element, the behavior of it's content is different in this case. Since the content must maintain the line breaks and spaces, the <pre> tag uses the attribute white-space: pre; by default. In your case, both the <pre> and <h3> elements behave like block elements, so their width is set by their parent. However, the text inside the <pre> element doesn't follow these rules and overflows, causing the scrollbar to show up on the parent.
In case the you're just using the pre tag for monospace font, you can apply a white-space: normal rule to the <pre> element.
Otherwise, if this HTML structure isn't a requirement, you can add the overflow: auto to the <pre> element instead, and remove it from the wrapper element.
pre {
overflow: auto;
margin-bottom: 0;
}
Edit:
In case you want the entire div to be scrollable, add a wrapper div around the <h3> and <pre>, and set it's display to inline-block. This will force the inner wrapper to take it's width from it's content, and will also force the block level <h3> to match this width. Check out this fiddle for a demo. This does introduce a vertical scrollbar, but removing the margin-bottom from the <pre> should fix that.
Edit 2: Yup, here's the fixed fiddle.
Currently you can solve your problem by defining the width of your h3 tag
demo
Alternatively, you can use
pre{white-space: pre-wrap;}
but this is not showing scroll bar as pre-wrap cathes 100% width and after then it shifts the word below the line.
Correct Way
remove overflow: auto; from your main div and add overflow: auto; to pre
demo
Note:
As pre tag is overwhelming the width 100% the h3 tag is showing the space in your demo.
You can either solve your problem by defining the width for h3 tag or including the tags in between text given in element.

How do I keep text from wrapping under an element which floats to its left?

I have two block elements. The first is floated to the left. I'd expect the right element to be a block as well and retain its square shape. Instead, text within it is wrapping under the element which is floating to the left.
.comment-date {
float: left;
}
<div class="comment-date">07/08 23:08</div>
<div class="comment-body">
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation.
</div>
The lorem ipsum text wraps under the date. I'd expect it to retain a block shape, floating to the right of the date. How can I achieve that?
Here is a fiddle:
http://jsfiddle.net/CS2Hs/
An alternative to the other solutions here would be to simply add a margin-left to .comment-body. It would also be helpful to apply a set width to .comment-date
.comment-date {
float: left;
font-weight: bold;
width: 90px;
}
.comment-body {
margin-left: 90px;
}
This will ensure that the text in .comment-body does not appear underneath the date.
Here is a demo:
--- jsFiddle DEMO ---
The body block is not in the float model. Simply set a float: left for .comment-body too. Also, you could use some widths. See: http://jsfiddle.net/CS2Hs/3/
I will try to understand your problem. As I understand, you want the .comment-body to be on the right and the .comment-date to be on the left but on the same line.
If I am right, maybe this will works:
.comment-date {
display: inline-block;
float: left;
width: 15%;
font-weight: bold;
}
.comment-body {
display: inline-block;
float: right;
width: 85%;
}
I made a JSFiddle just for you ;)
jsfiddle appears to be down at the moment so sorry if this doesn't work/isn't what you wanted but have you tried adding "overflow:hidden" to "comment-body"? This creates a new layout context which stops the text from wrapping underneath. I find this amazingly useful! Hope that helps!

Display Img and Div inline - it's not rendered inline

In order to follow correct web standards, I've tried to layout image and div inline. In orde to achieve that - I've used display:inline property.
But then I experienced the following issue: image renders from the center line, and div doesn't respect height parameter set to it. I've tried using line-height parameter, but that didn't give any useful results.
I've also tried various combinations with setting margin/padding to some values or to auto, or replacing div with span, or wrapping img and div with additional divs.
I've managed to achieve desired result by using position:absolute, but that doesn't help in cases where I want to use centered/relative positioning of the whole component...
Any clues or ideas or troubleshooting hints?
Please find the html example below:
<html>
<head>
<title>Test Page</title>
</head>
<body>
<div style="border: solid 2px green; height:40px;width: 600px;">
<span style="border:solid 2px green; position: absolute; height:50px; width: 50px;">
<i m g
style="display:inline; margin: 3px; padding:0px; border: solid 2px lightblue;"
height="38px"
width="38px"
src="someimage . JPG"
/>
</span>
<span style="position:absolute; left: 100px; width:400px; height:60px; margin:3px; border: solid 2px red;">
Some text that should be displayed in the center/middle of the div
</span>
</div>
<br />
<br />
<br />
<br />
<div style="border: solid 2px green; height:80px;width: 600px;">
<span style="border:solid 2px green; position: absolute; height:50px; width: 50px; vertical-align:bottom;">
123
</span>
<span style="position:absolute; left: 100px; width:400px; height:60px; margin:3px; border: solid 2px red;">
Some text that should be displayed in the center/middle of the div
</span>
</div>
</body>
</html>
Thanks for trying to help out.
First - the solution:
I've added few attributes to image tag and that helped a lot:
hspace="0" vspace="0" align="top" border="0"
Second: explanation:
Since I wanted to do "inline" (or "inline-block") thing, I had to figure out how inline/inline-block elements are laid-out by browsers. If you read CSS2 layout spec, you will soon find out that there is an issue with image and divs. Problem is with vertical-align - where image is aligned/rendered comparing to baseline, while divs go for bottom-line (or vice versa). That caused my example not be aligned.
Setting above mentioned params for the image tag helped.
Remarks:
Due to the complex history of IE5,6,7, Firefox, Gecko, WebKit, Chrome, CSS2 and BoxModel, there are some shortcomings to Layout model. Original problem comes from IE5 and 6 handling BoxModel in different way from CSS standard. That's maybe the main reason for having quirks mode and DTD standards.
However, this is a broad topic, if you want to find out more, I recoomend readin CSS2 spec and recommendation.
If you want to discuss it more - feel free to contact me via PM
Thanks again to all for helping and good luck with your Layouts
Kind regards
MP
Try this:
<div style="display: inline-block;"></div>
It's actually part of the CSS2 standard to display an inline thing as a block like a character.
One thing is, though, that <div>s are not supposed to occur inside of a <p> element, so you should instead use <span> tags.
I'm not sure exactly what you are trying to achieve. But it sounds like you want to float an image left with text in the div.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Test Page</title>
<style>
.wrap {
border: solid 2px green;
width: 600px;
overflow:hidden;
}
.myimg {
display:inline;
margin: 10px;
padding:0px;
border:solid 2px green;
height:70px; width: 70px;
float:left;
}
</style>
</head>
<body>
<div class="wrap">
<img src="myimagepath" class="myimg" />
<p>"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
</div>
</body>
</html>