div with inline-block not resizing - html

I have two elements, both with display: inline-block, and the parent has white-space: nowrap.
When the screen is resized, the div on the right side don't resize, like this.
I'm trying to make only the blue div resize.
Full source (jsfiddle)
The structure of the html is like this:
<div class="container">
<div class="header">...</div> <!-- red -->
<div class="aside">...</div> <!-- pink -->
<article>...</article> <!-- blue -->
</div>
Relevant css:
* {
box-sizing: border-box;
}
div.container {
margin: 0 auto;
max-width: 40em;
padding: 0;
white-space: nowrap;
}
div.container > * {
white-space: normal;
}
.aside {
display: inline-block;
max-width: 15em;
vertical-align: top;
}
.article {
display: inline-block;
max-width: 25em;
}

Old question, but for the sake of knowledge of anyone who reads this and also has the doubt:
What I've found is that setting position: relative on the .container
and position: absolute on the .article does what I want.
An absolute positioned element is positioned relative to the nearest positioned ancestor, where a positioned element means anything with a position property different to static, the default; if does not found any positioned element, uses the body element.
The absolute positioned elements, if has their width and heigth in auto, resizes to fit its content, and limits the maximun sizes by its positioned ancestor. You can check this putting a short string instead a large one: the element will shrink to the length of text. If you remove the positioning from div.container, the article (if still positioned absolute) will grow (depending on its content) to cover the space between previous element and body width.
And, related to the aforementioned and to add some utility to this delayed answer, a not-very-know bonus: if you define the right and left properties of a absoluted positioned element, and leave the width in auto, the element will cover the horizontal size between the right and left defined. This way you could put something like
article {
background-color: #a0f4ec;
display: inline-block;
position: absolute;
right: 0;
left: 30%;
}
div.aside {
background-color: #faf;
display: inline-block;
max-width: 15em;
width: 30%;
}
This trick also applies in a vertical sense, but with height, top and bottom properties.

There are a few ways to do it.
Method 1:
two divs the same line, one dynamic width, one fixed
Method 2 (negative margins)
http://alistapart.com/article/negativemargins

Unfortunately, Narxx's answers require the divs to be floated. I'm sure that's what you should do if you're building a real site, but in my case, I'm trying not to use it.
What I've found is that setting position: relative on the .container and position: absolute on the .article does what I want.
Simplified fiddle
If anyone can explain why, I'll mark it as an answer.

Related

Why doesn't "margin: auto" center an element vertically?

As you can see in the demo below, margin: auto; centers the blue div horizontally, but not vertically. Why not?
.box {
border: 1px solid red;
width: 100px;
height: 100px;
}
.center {
background: blue;
width: 50px;
height: 50px;
margin: auto;
}
<div class="box">
<div class="center"></div>
</div>
My question is not asking for workarounds.
As mentioned, this behavior is specified in section 10.6.2 of CSS2.1, and has remained unchanged from CSS2.
Block boxes are stacked vertically from top to bottom in normal flow. Furthermore, vertical margins may collapse, and only do so under certain circumstances (in your demo, the border on the parent element will prevent any margins on the child element from collapsing with its own). If you only have one such block box, and the height of the containing block is auto, then its top and bottom margins will be zero anyway. But if you have more than one block box in the same flow, or even out-of-flow boxes affecting the layout of in-flow boxes (in the case of clearance for example), how would you expect auto margins to resolve for those in-flow boxes?
This is why auto left and right margins are likewise zeroed out for inline elements (including atomic inlines) and floats (though horizontal margins never collapse). Inline-level boxes are laid along line boxes, and floats too obey unique layout rules.
Absolutely positioned boxes are a different story: since they are never aware of any other boxes in the same positioning context as themselves, auto top and bottom margins can be calculated for them with respect to their containing blocks without having to worry about any other boxes ever interfering.
Flexbox is also a different story: what sets flex layout apart from block layout is that flex items are by definition always aware of other flex items in the same flex formatting context, including the fact that there are none. In particular, neither can floats intrude into the flex container, nor can you float flex items to subvert this (although you can still remove a child element from flex layout completely with absolute positioning). Margins behave very differently with flex items due in part to this. See sections 4.2, 9.5 and 9.6.
Why...because the W3C spec says so.
If 'margin-top', or 'margin-bottom' are 'auto', their used value is 0.
As to the actual "why"...the query should really be addressed there.
It doesn't center the element vertically because it is a block-level element in the normal flow. Thus, the following rule applies:
If margin-top, or margin-bottom are auto, their used value is 0.
It's also worth pointing out that the rule above also applies to the following elements as well: (see points 10.6.2 and 10.6.3 for more information and conditions).
Inline replaced elements
Block-level replaced elements in normal flow
inline-block replaced elements in normal flow
Floating replaced elements
Block-level non-replaced elements in normal flow when overflow computes to visible
With that being said, absolutely positioned, non-replaced elements that don't have top, height, and bottom values of auto are an exception to this rule. The following applies from point 10.6.4:
If none of the three top, height, and bottom are auto and if both margin-top and margin-bottom are auto, solve the equation under the extra constraint that the two margins get equal values.
See the example below demonstrating how an absolutely positioned element is vertically centered using margin: auto. It works because none of the three properties top, height, and bottom have a value of auto:
.box {
border: 1px solid red;
width: 100px;
height: 100px;
position: relative;
}
.center {
background: blue;
width: 50px;
height: 50px;
margin: auto;
position: absolute;
top: 0; right: 0;
bottom: 0; left: 0;
}
<div class="box">
<div class="center"></div>
</div>
In addition, it's probably worth pointing out the following rule as well:
If one of margin-top or margin-bottom is auto, solve the equation for that value. If the values are over-constrained, ignore the value for bottom and solve for that value.
This means that if the absolutely positioned element has a margin-top value of auto and a margin-bottom value of 0 (i.e., margin: auto auto 0), the element would be absolutely positioned at the bottom relative to the parent like in the example below:
.box {
border: 1px solid red;
width: 100px;
height: 100px;
position: relative;
}
.center {
background: blue;
width: 50px;
height: 50px;
margin: auto auto 0;
position: absolute;
top: 0; right: 0;
bottom: 0; left: 0;
}
<div class="box">
<div class="center"></div>
</div>
Why doesn't margin:auto work vertically?
Actually, it does – just not for every display value.
If display is flex, margin: auto centers both vertically and horizontally.
The same applies to display: inline-flex, display: grid and display: inline-grid.
.box {
border: 1px solid red;
width: 100px;
height: 100px;
display: flex; /* new */
}
.center {
background: blue;
width: 50px;
height: 50px;
margin: auto;
}
<div class="box">
<div class="center"></div>
</div>
It's because of the actual possibility of knowing the true height of the element in which you want to center vertically in. To understand that, first think about how auto horizontal centering works. You have a div which you've given it a width (fixed or percentage). The width can be calculated to certain degree. If it's fixed width, great. If it's flexible or responsive (percentage) at least you have a range that the width will cover before it hits the next breakpoint. You take that width, minus whatever it's inside and split the remainder on both sides.
Now, with that information, how could the browser calculate the infinite amount of variations in which your div will grow vertically? Keep in mind the size of the element, wrapping of text, paddings, and responsiveness will also alter the width and force the text to wrap further, and on, and on it goes.
Is it an impossible task? Not really, has CSS spent time and effort covering this? Not worth their time, I guess.
And that is basically the answer I tell my students.
But....fret not! Bootstrap v4 alpha has figured out vertical centering!
EDIT
Sorry to edit this late but I thought you may want to consider this solutions to center vertically and it is pretty simple by making use of the calc function
<div class="foo"></div>
.foo {
background-color: red;
height: 6em;
left: calc(50% - 3em);
position: absolute;
top: calc(50% - 3em);
width: 6em;
}
See it HERE

Display table cell height 100% align image bottom

I'm using a table layout and attempting to set the height of the child of table-cell to be 100% of it's container. Why does this not happen and how do you resolve this?
I also tried setting the table-cell height to 100% without success.
I would like to align ONLY the images to the bottom of the container. How can I do that within a table display?
The amount of text in each table cell is dynamic
Fiddle: http://jsfiddle.net/3u3gpf2n/1/
It seems like you're trying to create a 3-column, 2-row table, but only using single rows in order to keep your markup semantic. Without flexbox, distributing the image to the bottom will require some CSS trickery.
One example, which should fit your requirements of (1) cross-browser, including IE, compatibility (2) allow for arbitrary text in the box is:
*{
padding: 0;
margin: 0;
}
#container{
width: 500px;
margin: 0 auto;
}
ul{
list-style-type:none;
display: inline-table;
}
li{
position: relative;
/* image width / (image height * column count) */
padding-bottom: 11.764705882%;
display: table-cell;
background: red;
/* 100 / column count */
width: 33.333%;
}
a{
color: white;
}
img{
width: 100%;
position: absolute;
bottom: 0;
}
<div id="container">
<ul>
<li><a href><div class="header">Xiao Huang</div>
<img src="http://3door.com/sites/default/files/styles/ablum_306_108/public/special/xiao_huang_ren_fu_ben_.jpg?itok=cPnwgTyV" /></a></li>
<li><a href><div class="header">Xiao Huang</div>
<img src="http://3door.com/sites/default/files/styles/ablum_306_108/public/special/xiao_huang_ren_fu_ben_.jpg?itok=cPnwgTyV" /></a></li>
<li><a href><div class="header">Xiao Huang Xiao Huang Xiao Haung</div>
<img src="http://3door.com/sites/default/files/styles/ablum_306_108/public/special/xiao_huang_ren_fu_ben_.jpg?itok=cPnwgTyV" /></a></li>
</ul>
</div>
I've added a relative position to the LI, and absolutely positioned the Image. To ensure things work correctly, I've given the cells a percentage-based width. I've also added padding to the bottom.
The one thing that this doesn't include is the cursor all the way down. If the user clicks between the image and text, the anchor will not be triggered.
To fix this, consider removing the UL/LI, and styling the anchor tags as table-cells and the wrapping DIV (or NAV, if you have a JS shim for HTML5 tags) as table.
I'm using a table layout and attempting to set the height of the child
of table-cell to be 100% of it's container. Why does this not happen
and how do you resolve this?
I also tried setting the table-cell height to 100% without success.
When using percentage heights in CSS you need to specify the height for all parent elements, up to and including body and the root element (html).
From the spec:
CSS height property
percentage Specifies a percentage height. The percentage is calculated with respect to the height of the generated box's
containing block. If the height of the containing block is not
specified explicitly and this element is not absolutely positioned, the value computes to 'auto'.
auto The height depends on the values of other properties.
In other words, if you have not set an explicit height to the containing block (and the child is not absolutely positioned), then your child element with percentage height will have no frame of reference.
So the problem in your code boils down to this: You're missing a height on parents ul, #container, body and html.
DEMO: http://jsfiddle.net/sedetcc6/
I would like to align ONLY the images to the bottom of the container. How can I do that within a table display?
Although vertical-align is well-suited for aligning elements in a table cell, in this particular case, because each image has a sibling that must not move, the vertical-align property is not useful.
But the images can be shifted with absolute positioning. Try this:
li{
display: table-cell;
background: red;
height: 100%;
position: relative; /* establish nearest positioned ancestor for abs. positioning */
width: 33.33%; /* new */
}
img{
width: 100%;
position: absolute; /* new */
bottom: 0; /* new */
}
DEMO: http://jsfiddle.net/sedetcc6/1/
NOTES:
No changes to original mark-up
For the record, this problem could be easily solved with flexbox, but I understand it's not an option here due to a need for IE 8 & 9 browser support.
I hope I am understanding the problem correctly, but my advice would be to make each anchor display: table-cell so they are forced to the same height, and then you can position all elements inside the anchor or even use background images instead of <img />
JS fiddle here
All you need to need is set a height for all your elements, e.g.
*{
height: 50px;
}
You'll get your desired result: http://jsfiddle.net/asimplepeter/3u3gpf2n/10/
If the amount of text is going to be an issue, you can set overflow: auto for your .header class.
Your code and display properties like 'table' and 'table-cell' things are correct.
But, the problem is that tables are rendered with auto height only. Because of this, eventhough you had set your container height, the table structure was not rendered with the proper height. So, along with container class, set height for 'ul' as well
regarding the position of image, you can set your margin-top to 100% or by calculating the size of the image and reducing that from the 500px container height will help you in positioning.
Hope this answers your all queries
EDIT As setting the margin is expand the table height, alternatively you can use css property like below
transform: translateY(Y);
transform-origin: left top;
In this case, i would think it is better mantain the height of cell according to the img because it's static and set header as absolute.
Something like that:
li{
position: relative;
display: table-cell;
background: red;
height: 100%;
vertical-align: bottom;
}
.header{
width: 100%;
position: absolute;
display: block;
color: white;
background: blue;
}
http://jsfiddle.net/3u3gpf2n/12/

Centering in the unknown

I would like to center and clamp the dimensions of a child div inside its parent.
<style type='text/css'>
.parent {
width: 100%;
height: 100%;
}
.child {
max-width: 100%;
max-height: 100%;
}
</style>
<div class="parent">
<div class="child">
<img src='dog.jpg' />
</div>
</div>
Here are the constraints:
The parent div is set to occupy the entire screen (of unknown size), so width:100% and height:100%.
The width and height of the child div are unknown. In one use case, the child div contains an image. In another, it contains a video.
The width and height of the child div must be constrained to the size of the parent, so max-width: 100% and max-height: 100%.
The child div must be vertically and horizontally centered inside the parent.
Ideally, this should work without javascript.
IE can be left unsupported :)
I've tried all the techniques listed in this excellent article, 'Absolute Centering in CSS' , and none of them pan out. Here's why:
Absolute centering: In order for this technique to work with a child of unknown size, you must set display:table on the child. You can then constrain the max-width of the child's contents, but not the max-height, because by CSS 2.1 rules, tables render to fit their contents.
Negative margins: Doesn't allow for variable height.
Transforms: Undesirable because it can result in blurry rendering.
Table-cell: Fails for the same reason that absolute centering fails, i.e. table rendering.
Inline-block: Doesn't work in the important case where the child is 100% width.
Flexbox: Works well until a window resize occurs, at which point you have to force a Webkit redraw to propagate the centering changes. This hack does the job, but it's still a hack. I want to believe there's a more elegant solution to this.
Best solution here is to use :before pseudo element. Check out this article on centering the unknown, http://css-tricks.com/centering-in-the-unknown/
SEE THE DEMO HERE
body,html {
width: 100%;
height: 100%;
margin: 0;
}
.container {
text-align: center;
background: #ccc;
width: 100%;
height: 100%;
}
.container:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
margin-right: -0.25em; /* Adjusts for spacing */
}
.image {
display: inline-block;
max-width: 100%;
max-height: 100%;
vertical-align: middle;
padding: 10px 15px;
border: #a0a0a0 solid 1px;
background: #f5f5f5;
}
You could use display:table and display:table-cell like so Jsfiddle. Though this will just center the image of the child div.
If you need to have a centered div around the image you could always add another div inside of the child div with the style display: inline-block example

How can I lay out two <div>s on one line, and have one centre-aligned (relative to the entire line) and the other right-aligned?

I want to display 2 divs in a single line. I have a parent div and two child divs.I want to keep the width of first child div and parent div equal. So the header(label of first child div) displays always middle position of parent div and I want to display the second child div at the right side in the same line of parent div.(Condition is always label of first child div should display middle of parent div). Here is the jsfiddle.
If I were styling this header section for a website, and I wanted some flexibility in styling the various elements, here is out I would start.
For my HTML:
<div class="head">
<div class="innerfirst">
<h1>ABCDEF GHIJ</h1>
</div>
<div class="innersecond">
<label>RIGHT1</label>
<label>RIGHT2</label>
</div>
</div>
I would put the page title in a <h1> tag so that I can adjust font-size, padding, background color and so on. In fact, you could add a tag line below the title line and various background images. Having .innerfirst and h1 gives you quite a bit of flexibility.
The <label> tags don't make sense semantically in this context, but perhaps you will have have input fields later like a search box.
For the CSS:
.head {
background-color:#2191C0;
width: 100%;
height: 85px;
position: relative;
}
The above is fine, set position: relative so that you can use absolute positioning for one of the child elements. The fixed height is a good idea, makes it easier to adjust elements vertically.
.innerfirst {
}
.innerfirst h1 {
text-align: center;
color: #FCFCFC;
padding-top: 10px; /* You could also use a margin... */
}
By default, .innerfirst will have 100% width since it is an in-flow block element, same with the h1 element. You can center the text within h1, and adjust color, padding and margin as needed.
.innersecond {
border: 2px solid lightgray;
color: white;
position: absolute;
width: 25%; /* Set this or by default it will shrink-to-fit content */
height: 61px; /* Set this or by default it will shrink-to-fit content */
top: 5px;
right: 5px;
padding: 5px;
}
What you could do is create a box of text and absolutely position it to the right. It is a good idea
to set a height and width otherwise, as a result of the absolute positioning, the div will shrink to fit the content, which is sometimes useful. The top and right offsets will position the .innersecond to the top-right of the parent container because you set position: relative in .head.
.innersecond label {
display: block; /* optional if you want block behavior */
border: 1px dotted white;
}
Finally, if you want the label tags to behave like blocks, use display: block and style according to you design requirements.
For reference, demo fiddle: http://jsfiddle.net/audetwebdesign/qpb9P/
Here's an updated jsfiddle. Read up on the display property!

Lack of outermost margin with smaller viewport

I have a <div id="wrapper"></div>​ with
#wrapper {
height: 300px;
margin: 10px;
position: absolute;
top: 0;
left: 0;
width: 400px;
}​
When I resize the viewport so that horizontal scrollbars appear, the right margin disappears; I can only scroll as far right at the element's content, but I want the margin to be present on all sides. It also happens to the left margin if right: 0; is applied, and to the bottom margin if the viewport is made shorter. Giving wrapper a position: static; (default) makes no difference.
Why is this happening? It doesn't follow normal margin collapse rules. How can I get my margin back? I've tried giving the body padding/margin.. nada.
jsFiddle
Background Info
The default width of the body element is the html width which is also the window width (or iframe width in such a case). The default behavior of a block level element is that the scroll only accounts for the actual element (hence, it doesn't care about the right margin if there is nothing more to display on the right). This causes your right margin issue. (By the way, according to this article, the scroll bars are actually appearing on the html element, not the body.)
For Position: Absolute
By having #wrapper with position: absolute, the body element ends up with zero height. This causes your bottom margin issue in this case.
A solution is to account for the margins like so (see fiddle):
body {
min-height: 320px;
min-width: 420px;
}
This assigns a minimum dimension to the body equal to the width + margins and height + margins of the absolute element.
Now, I'm not sure what you expect to happen if you have right: 0 set, as forcing a left margin to "remain" just ends up causing, in my opinion, a premature scroll bar to activate. See this fiddle.
Regarding Position: Static
The default block level behavior can be changed by forcing a shrink-wrap like behavior on the body element using (see fiddle):
body { display: inline-block; }
Note: that body { float: left; } did not give me the same shrink-wrap behavior (see fiddle).
The inline-block element will account for the margin of its inner elements to determine its own width, which then allows the right margin to work.
The reason the display: inline-block; solution does not work on the #wrapper being position: absolute is because it makes the body have a zero width and height, since the absolute positioning takes that element out of flow and there is nothing left inside body to give it dimension.
The above was currently only tested on IE9.
I'm afraid there's only one simple and quick solution, and that is to create a new div inside the wrapper div.
http://jsfiddle.net/QHKmN/2/
CSS
#wrapper {
background: black;
height: 300px;
margin: 10px;
position: absolute;
top: 0;
left: 0;
width: 400px;
}
#inwrapper {
background: green;
height: 290px;
margin: 5px auto;
position: relative;
width: 390px;
}
​
HTML:
<div id="wrapper">
<div id="inwrapper">
</div>
</div>
​
And there's your margin.