A simple block element won't expand vertically unless its contents are of inline-block or block.
See fiddle: https://jsfiddle.net/4148xjvv/7/
Or see code:
HTML:
<div class='parent'>
<span class='padding'>Inline</span>
</div>
<br><br>
<div class='parent'>
<span class='inline-block padding'>Inline-block</span>
</div>
<br><br>
<div class='parent'>
<div class='padding'>Block</div>
</div>
CSS:
.parent {
background-color: red;
color: white;
}
.padding {
padding: 10px;
}
.inline-block {
display: inline-block;
}
Result:
The lateral padding works, but the vertical does not.
Chrome debugger shows that the padding is there, but bleeds out of the parent.
Obviously this isn't a huge issue, I can just change the children to inline-block if I need padding, so I want to know why this is happening.
I found this article to be very helpful in understanding what is happening: https://hacks.mozilla.org/2015/03/understanding-inline-box-model/
Any vertical padding, border, or margin applied to an element will not push away elements above or below it.
Basically, as you can see from the image above, the padding is added, it just doesn't change the vertical position of the element.
you are adding the padding to a span element, which is an inline element, where vertical padding won't move the element - its baseline (and therefore the text) stays where it is, due to the inline property of the span element.
therefore the vertical padding can only work in conjuction with the inline-block setting in your second parent element - or in your third parent element where you add it to a div element.
Related
JSFiddle demo
In a dropdown with a container element set to display: inline-block, there is a label (always visible, toggles dropdown overlay), and the overlay element itself. I am setting the overlay container to height: 0 and wishing to allow the overlay contents to exceed the height of the container, without affecting any parent elements. However, I am seeing some strange results - the overlay container is causing the parent of the dropdown to fully enclose the overlay contents too!
In the following HTML, ib = the inline block and h0 = the height:0 overlay container. See the jsfiddle demo to see it in action.
<div>
Sort by this
<span id="ib">
<span>LABEL</span>
<div id="h0">
DROPDOWN<br />
</div>
</span>
</div>
I don't wish to use position: absolute on the overlay, as I would like the contents of the overlay to drive the final width of the label. Surprisingly, I can achieve the desired outcome with the following css:
#ib { display: inline-flex; flex-direction: column; }
I'm happy to use that workaround for now, but also interested in the "why" behind this bizarre effect.
Your issue is about vertical-align rule for inline block elements. By default it baseline, here is some spec:
Baseline: Align the baseline of the box with the baseline of the parent box.
See also:
The height of each inline-level box in the line box is calculated. For replaced elements, inline-block elements, and inline-table elements, this is the height of their margin box; for inline boxes, this is their 'line-height'.
source: https://www.w3.org/TR/CSS2/visudet.html#line-height
and
CSS assumes that every font has font metrics that specify a characteristic height above the baseline and a depth below it. In this section we use A to mean that height (for a given font at a given size) and D the depth. We also define AD = A + D, the distance from the top to the bottom.
source: https://www.w3.org/TR/CSS2/visudet.html#inline-box-height
So your fix is ignore default inline-level block height setted via line-height and font-size by setting vertical-align: top/bottom/middle/text-top/text-bottom by your choice.
And fixed code:
.dropdown {
display: inline-block;
vertical-align: top;
}
.overlay {
height: 0;
}
<div>
sort by this
<span class="dropdown">
<span>LABEL</span>
<div class="overlay">
DROPDOWN<br />
DROPDOWN<br />
DROPDOWN
</div>
</span>
</div>
<hr />
I am trying to build a horizontal scrolling layout, composed of image blocks:
<div class="container">
<div class="item">
<img src="http://placehold.it/200x300">
</div>
<div class="item">
<img src="http://placehold.it/400x300">
</div>
<div class="item">
<img src="http://placehold.it/300x300">
</div>
</div>
I used display:inline-block and white-space: nowrap; properties to achieve this, and it does work but browsers don't seem to recompute block widths on resize?
Check here: https://jsfiddle.net/g597w3Lr/2/ and try resizing the browser..
Here is a screen grab to better understand what is my problem:
https://youtu.be/VxKo4gysc1o
At first all images are well positioned and i can scroll horizontally: perfect.
I then resize the browser
images are resizing, not the .item wrappers. White gaps appear :(
Basically i was expecting same feature as with vertical scrolling, i.e. adapting width depending on content size.
I actually dont even understand the logic here..
Is there any way to get over this?
Thanks!
Original answer
EDIT 2: Looking at your video I think the new approach is what you are looking for.
You have to display your divs with .item class as inline and remove your white-space: normal property.
.item {
display: inline;
height:100%;
}
Updated JSFiddle.
Explanation:
I am not an expert of CSS so if someone see some mistake please correct me.
When you display an element as inline-block as the official documentation says:
inline-block
Causes an element to generate an inline-level block container. The inside of an inline-block is formatted as a block box, and the element itself is formatted as an atomic inline-level box.
which means that the element that you display as inline-block acts like a block but you can set it inline (in the same line). This means that you can set a div (which is display: block as default) in a single line. You can also see it here:
The div element, short for division, is the block level generic container.
Also, inline elements cannot get height/width properties so this is the reason why when you display your divs with .item class as inline, they wrap the content but not get the height/width that they should correspond to take (from their parents in your case, as you put them with %).
If you display them as inline-block it does not changes anything about their default height/width properties. Just allows you to display them in a single line.
JSFiddle to see the three divs (inline/ inline-block / block, as default).
You will have to modify slightly your css
HTML
<div class="container">
<div class="item">
<img src="http://placehold.it/200x300">
</div>
<div class="item">
<img src="http://placehold.it/400x300">
</div>
<div class="item">
<img src="http://placehold.it/300x300">
</div>
</div>
CSS
html,body {
height:auto;
}
.container {
display: inline-block;
white-space: nowrap;
height:auto;
}
.item {
display: inline-block;
white-space: normal;
}
.item img {
width:100%;
height:100%;
}
Fiddle
check it see that's what you want ?
I manage your classes with border:solid 1px red;
and use width:100% in some classes.
also in class item:
width:100%;
https://jsfiddle.net/g597w3Lr/6/
I still have problem to well understand how the float property works in CSS. I do apologize because I know this is css basics but I really want to understand that and get a good explanation. I've created an example to show you.
Here is my page :
I just want to resize the second div at the right. When I look at it in the Chrome Developer Tools, I see that this div begins at the top left of the window and not after the red square. I'd like it to begins just after the red square to change the width properly without calculating the size of the square and doing something like
width = square size + width i want
Do you know how this it happens and how to properly resize the width of the second div ?
EDIT: the solution consists in add the float property to the second div too. The explanation is the following : floated elements are removed from the flow, so they don't stack with the non-floated elements.
You need to set float for another div too.
We generally do like below:
html
<div class="float-left">
<p>floated left</p>
</div>
<div class="float-left"><!--- to float next to previous div--->
<p>floated left</p>
</div>
css
.float-left{
float: left;
}
As per your comment:
We do clear the float values because the container contents would never been collapsed.
You need to float the second div.
Heres an example.
<div class="parent-div">
<div class="left">
</div>
<div class="left">
<p>This is the description of the image</p>
</div>
</div>
You need to set
p { display:inline; }
or
div { display:inline; }
since paragraphs and divs are block elements.
http://www.w3.org/TR/CSS2/visuren.html#block-boxes
the reason is that floated elements are removed from the flow, so they don't stack with the non-floated elements. - therefore they don't "take up space" like before. This is why your text div starts at the top left of its container.
from MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/float
The float CSS property specifies that an element should be taken from the normal flow and placed along the left or right side of its container, where text and inline elements will wrap around it. A floating element is one where the computed value of float is not none.
You have to set float for both DIVs
Here is the updated code:
HTML:
<div id="main_container">
<div class="left"></div>
<div class="right">
<p>This is the description of the image <i>Random text</i>
</p>
</div>
<!--Comment below <DIV> to see the result-->
<div class="clear"></div>
</div>
CSS
#main_container {
border:5px solid #000;
}
.left, .right {
width: 100px;
height: 100px;
background: red;
float:left;
}
.right {
background: blue;
width: calc(100% - 100px);
}
.clear {
clear:both;
margin:0;
padding:0;
}
Also, just to add one more important fact related to "float" is, make sure you add "clear:both" property after "float".
Why?? Because, a common problem with float-based layouts is that the floats' container doesn't want to stretch up to accomodate the floats. If you want to add, say, a border around all floats (ie. a border around the container) you'll have to command the browsers somehow to stretch up the container all the way.
Here is the Fiddle for the same: http://jsfiddle.net/1867ud9p/7/
Hope this will help!
I have the following div
<body>
<span style="border:1px solid red; display:inline-block">
Some text<br />
<hr />
some more text
</span>
</body>
In "normal" web browsers, the width of the div is calculated to fit the text. And the hr is 100% of the div.
But in IE7 the hr causes the div to expand to 100% of the body.
Is there any clever css I need to add somewhere so it behaves correctly in IE7?
Please note, I can't set any fixed width.
In IE6/7, display:inline-block only works on elements that are inline by default (e.g., span). So if you try setting a div to display:inline-block, it won't work in IE6/7.
An inline element will size itself to the width of its content. An inline-block element will do the same by default, if it's not given an explicit width. If the hr is 100% (100% of its parent, which in turn is 100% of the child), then there's a circular definition for the hr width that may not work as expected (100% of what? 100% of itself).
To avoid a circular definition for the width that may not work as expected in some browsers (especially IE6/7), either the container of the hr (div, span, or whatever) should have a defined width (in px, %, or em) or the hr itself should have an explicit width (in px or em). Otherwise, the width is not defined in any identifiable way, and it's left up to the browser to decide what to do by default.
If you can't set any widths, that may rule out using an hr tag. And based on the tests I ran, the options don't look very good for CSS solutions either (without setting a width).
Edit:
I think the only way to do this without setting widths or relying on JavaScript or jQuery, is if it's acceptable to have a horizontal line after every line of text (including any long paragraphs that wrap around to the next line, if there are any). In that case you could add a bg image to the container that contains a horizontal line at increments equal to the line-height of the text, displayed at a vertical offset equal to the line-height so a line doesn't appear at the top of the first line of text.
HTML
<div class="main">
<p>This is the first line.<br/>
This is the second line.<br/>
This is a long line that will wrap around to the next line if the container is not very wide.
</p>
</div>
CSS
.main {
background: url(image.png) repeat-x left 15px;
}
p {
font-size: 12px;
line-height: 15px;
}
jsfiddle demo
The width property of the <hr> tag has been deprecated, so you're styling options are limited on the <hr> tag.
15.3 Rules: the HR element
Index of Attributes
A more modern approach is to use the border property of a <div> instead.
Image rendered by IE 7:
Image rendered by Chrome 19:
jsFiddle Demo
HTML
<body>
<div style="border:1px solid red; float:left;">
<p>
Some text
</p>
<p class="border-top">
some more text
</p>
</div>
</body>
CSS
.border-top{
border-top:#000 1px solid;
padding-top:1em;
}
Note: IE 6 & 7 don't support display:inline-block, so you might need to use float:left instead. The article below compares the use of the aforementioned properties:
CSS display: inline-Block: Why It Rocks, And Why It Sucks
Found a method at a blog. The original one required modernizer.js. I've edited it.
HTML:
<div class="hrdemo"><hr /></div>
CSS:
.hrdemo hr {
display:none
}
However, if your div.hrdemo is inside some floated container; you may have to assign a fixed width for it (for IE7).
I have displayed one of sprite's image in span tag. The span is in inside of the some other element like <div>, <li>, <p>. The parent elements of the span's, text alignment is center.
The text content of the parents elements are aligned center correctly. But i am not able to
make the span with sprite image to center.
Here i have added the sample code.
HTML Markup:
<div align="center"><span class="cameraIcon spriteImage"></span>Some Text Content</div>
Style
span.cameraIcon {
background-position: -240px 0;
width: 24px;
height: 24px;
position: absolute
}
Any suggestions would be appreciative.
Thanks!
By using absolute positioning, the span tag is no longer part of the text flow inside the div element, so it's not affected by text alignment.
You could use the style display: inline-block; to make the span element a block element that is still part of the text flow. (Some older browsers doesn't support that display value, though.)
It seems that the span serves no other purpose than to show a background image, so I would get rid of it completely and add the background to its parent element:
html:
<div class="cameraIcon spriteImage">Some Text Content</div>
css:
.cameraIcon {
background-position: -240px center;
}