Left/right positioning takes border size into account - html

My goal is to be able to dynamically position a DIV so that it is visually precisely underneath it's parent - i.e. so that it is the same width as it's parent, and begins 0 pixels from the bottom of the parent's left border.
Essentially, the end result should be something like this:
http://jsfiddle.net/cvz3gvbs/
Here I simply use a relatively positioned parent DIV, and an absolutely positioned child DIV. I then simply use the left and top positioning attributes to move the child DIV into place.
However, you'll notice in that fiddle that in order to make this happen, I had to set left: -10px on the child DIV. The reason is that if I don't, this happens:
http://jsfiddle.net/cvz3gvbs/1/
Here, the child DIV is not directly centered underneath the parent. The reason seems to be that the left and right position values take into account the border of the parent, so that left: 0px means positioned directly to the right of where the parent border ends.
So I have to compensate for this with a negative left value. That's fine, except if I want to be able to do this dynamically with Javascript, I might not know in advance the thickness of the parent border - (or even if the parent even has a border). So I can't simply hardcode a negative pixel value in the style sheet. I'd have to use Javascript to dynamically query the computed styles of the parent element and determine the border width of the parent, which is a bit cumbersome.
Question: Is there some way to do this without using Javascript to discover the border width?
I thought this might have something to do with the W3C box model, since left was taking into account the border of the parent. So, I tried using the box-sizing: border-box property so that the browser would include the border-width in the box size - but this had no effect. A left value of 0px still means positioned directly to the right of the parent element's border.

Is it a necessisty that .bar be inside .foo? You could make them siblings and wrap them in a container set to relative like so. You don't even need to set the width on each of them, just on their parent:
HTML
<div class="container">
<div class = "foo"></div>
<div class = "bar"></div>
</div>
CSS
.container{
width: 200px;
position: relative;
}
.foo {
border: 10px solid #000000;
height: 45px;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
}
.bar {
box-sizing: border-box;
position: absolute;
top: 35px;
left: 0;
right: 0;
border: 1px solid #000000;
height: 500px;
}
FIDDLE

You should add them in a container like this example
<div>
<div class = "foo"></div>
<div class = "bar"></div>
</div>
http://jsfiddle.net/cvz3gvbs/6/
and you can remove the position of the class bar

Related

Override max-width margins of parent container?

I am setting up a max-width on my site's main container so that it doesn't appear comically wide on large screens, resulting in left and right margins on the main container. One piece of content we have is dynamically generated and could potentially be very wide. On large screens it's currently pushed over by the main containers left margin, aligning it with the rest of the content of the page, but I would like for it to align with the true left edge of the body instead of the edge of the container.
This picture shows some regular content with the expected margins, and my large content (a tournament bracket) overflowing off the right edge of the screen. I'd like to shift it to the very left.
Is there any way to do this without having to move it outside of the container? Additionally, is there an easy way to make it only do this when it would otherwise be larger than the main container (or even better, only when it would go off the right edge of the screen)?
Here's a generic solution that keeps the child element in the document flow:
child {
width: 100vw;
position: relative;
left: calc(-50vw + 50%);
}
We set the width of the child element to fill the entire viewport width, then we make it meet the edge of the screen by moving it to the left by a distance of half the viewport, minus 50% of the parent element's width.
Demo:
* {
box-sizing: border-box;
}
body {
margin: 0;
overflow-x: hidden;
}
.parent {
max-width: 400px;
margin: 0 auto;
padding: 1rem;
position: relative;
background-color: darkgrey;
}
.child {
width: 100vw;
position: relative;
left: calc(-50vw + 50%);
height: 100px;
border: 3px solid red;
background-color: lightgrey;
}
<div class="parent">
Pre
<div class="child">Child</div>
Post
</div>
Browser support for vw and for calc() can generally be seen as IE9 and newer.
Note: This assumes the box model is set to border-box. Without border-box, you would also have to subtract paddings and borders, making this solution a mess.
Note: It is encouraged to hide horizontal overflow of your scrolling container, as certain browsers may choose to display a horizontal scrollbar despite there being no overflow.
You can position it relative so that you will be able to use left property and position it to left end , using appropriate values ( can't say which value will work as you haven't provided code )
If you want to position that when it is larger then you can apply a JS function and call it to measure width ( spanning that is offsetWidth) of your element .
If it's value exceeds a certain value then
apply style.position = "relative" ,
style.left = "somePreferredvalues"
else apply style.position = "static"
I will be sure about the position being absolute or relative if you provided your code . So try with both once

Container div does not expand to fit child div (without floats)

My container div does not expand to fit its child div - which has a top: 20px value.
I don't even have floats and have used both overflow:hidden (cuts part of the child div) or overflow:auto (creates scrollbars).
See codepen example: Codepen
<div class="container">
<div id="model">fdsf</div>
</div>
Appreciate any solutions to this problem.
Remove top and position properties and use margin: 10px auto 0 auto;
#model {
background: yellow;
border: 1px solid orange;
width: 100px;
height: 100px;
margin: 10px auto 0 auto;
display: block;
}
Demo
1) In your example, the container is expanding to fit the child div correctly. The height of the child is 100px plus two times the border of 1px, in total 102px. Then, the height of the container is exactly 102px, as the developer tools in any browser can tell you.
Height of the contents totals 102px, thus the inner height of the container is 102px. This is by definition "expanding to fit the contents".
2) Now, you are setting position: relative for your child div. The following quote from Mozilla Developer Network should give a complete explanation to what is happening in your example.
Relative positioning:
This keyword lays out all elements as though the element were not
positioned, and then adjust the element's position, without changing
layout (and thus leaving a gap for the element where it would have
been had it not been positioned). The effect of position:relative on
table-*-group, table-row, table-column, table-cell, and table-caption
elements is undefined.
3)
Obviously, you can get rid of this effect by getting rid of relative positioning, and just using margin instead. Regarding your comment, no, top, right, bottom, and left should absolutely not work. They are meant to be used for a totally different thing, for what the quote above explains.

Is it possible to position an element relative to the border-box of its parent?

Consider the following jsfiddle for reference:
http://jsfiddle.net/apmmw2ma/
<div class='outer'>
<div class='inner'>
Inner.
</div>
Outer.
</div>
div.outer {
position: absolute;
left: 10px;
top: 10px;
border: 5px solid green;
padding: 10px;
}
div.inner {
position: absolute;
left: 0;
top: 100%;
border: 10px solid red;
padding: 15px;
}
As you can see, the “inner” box (with the red border) is positioned relative to the outer’s padding-box: left:0 positions it just to the right of outer’s border, and top:100% appears to mean “100% of the content plus padding, but not the border”.
Unfortunately, adding box-sizing: border-box to the outer div seems to have no effect.
I want to position a child element directly below its parent’s border-box, i.e. the two borders should abut no matter how thick they are. Is this possible?
Unfortunately this is not possible without knowing the border widths in advance. If you don't know the border widths in advance, or if they are dynamic, then you're out of luck.1
The area of an element's containing block is indeed defined as the padding edge of the element forming the containing block. This is explicitly stated in the spec, and is by design; descendants aren't normally supposed to overflow the border of their container, unless the container has overflow: visible and does not establish a BFC (and even then, the effect is only visual; it doesn't affect layout). Otherwise, the border isn't much of a border anymore.
Generally, if you want to lay out elements such that they interact by their border or outer edges, you don't want to lay them out as ancestors and descendants. At the very least you want them to be siblings2, otherwise they should be completely unrelated.
This seems like an oversight to me; the meaning of top: x% should really depend on the box-sizing value of the parent...
The purpose of box-sizing is to change how the size of a box is calculated (i.e. whether or not the padding or the borders should add to the dimensions specified by width and height); while you can use it to alter the size of an element's padding box, the area of the containing block, if the element generates one, is still defined by that padding box.
1 This could conceivably be solved with custom properties, but on the precondition that you must assign the same custom property to both the parent's border-width and to the child's respective offsets, which is basically another way of saying "you must know the border widths in advance" or at least, have control over them.
2 Floats, for example, are highly predisposed to the border edge of boxes, so much so that they can appear to collapse margins in places where you normally wouldn't expect it to occur.
Unfortunately it is not possible to do this without repeating the value of the parent’s border width.
However, if repeating the border width value is acceptable, the following solution works:
div.inner {
top: <desired top value, e.g. 100%>;
margin-top: <parent’s border-bottom-width>;
left: <desired left value, e.g. 0>;
margin-left: -<parent’s border-left-width>;
}
In the future, the same will be possible with calc(), which at the time of this writing is not widely enough supported:
div.inner {
top: calc(<desired top value, e.g. 100%> + <parent’s border-bottom-width>);
left: calc(<desired left value, e.g. 0> - <parent’s border-left-width>);
}
If I may dream for the future, I would like to be able to refer to the property values of the parents/ancestors inside a calc() expression. Then I could write something like:
/* Hypothetical code that will never work */
div.inner {
top: calc(100% + parent.border-bottom-width);
left: calc(0 - parent.border-left-width);
}
Use box-shadow
This makes use of the box-sizing model the way you expect:
http://jsfiddle.net/apmmw2ma/6/
-webkit-box-shadow:inset 0px 0px 0px 5px green;
-moz-box-shadow:inset 0px 0px 0px 5px green;
box-shadow:inset 0px 0px 0px 5px green;
box-sizing:border-box;
-moz-box-sizing:border-box;
-webkit-box-sizing:border-box;
Try using display:table; for the outer div.
Fiddle: http://jsfiddle.net/apmmw2ma/9/

CSS property to pad text inside of div

Is there a way to give a div element some padding INSIDE its border? For example, currently all the text inside my main div element goes right to the edge of the element's border. I'd like, as a general rule on this site, to have at least 10 to 20 px of space between the text and the border.
Here's a screen shot to illustrate what I currently have:
The CSS property you are looking for is padding.
The problem with padding is that it adds to the width of the original element, so if you have a div with a width of 300px, and add 10px of padding to it, the width will now be 320px (10px on the left and 10px on the right).
To prevent this you can add box-sizing: border-box; to the div, this makes it maintain the designated width, even if you add padding.
So your CSS would look like this:
div {
box-sizing: border-box;
padding: 10px;
}
you can read more about box-sizing and it's overall browser support here:
https://www.paulirish.com/2012/box-sizing-border-box-ftw/
I see a lot of answers here that have you subtracting from the width of the div and/or using box-sizing, but all you need to do is apply the padding the child elements of the div in question. So, for example, if you have some markup like this:
<div id="container">
<p id="text">Find Agents</p>
</div>
All you need to do is apply this CSS:
#text {
padding: 10px;
}
Here is a fiddle showing the difference: https://jsfiddle.net/CHCVF/2/
Or, better yet, if you have multiple elements and don't feel like giving them all the same class, you can do something like this:
.container * {
padding: 5px 10px;
}
Which will select all of the child elements and assign them the padding you want. Here is a fiddle of that in action: https://jsfiddle.net/CHCVF/3/
Just use div { padding: 20px; } and substract 40px from your original div width.
Like Philip Wills pointed out, you can also use box-sizing instead of substracting 40px:
div {
padding: 20px;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
The -moz-box-sizing is for Firefox.
Padding is a way to add kind of a margin inside the Div.
Just Use
div { padding-left: 20px; }
And to mantain the size, you would have to -20px from the original width of the Div.

How to prevent padded child element to overflow its parent?

As you can see from this example, the input seems to "overflow" its parent div. I'd like to add padding to the input without making it overflow its parent.
I would like to know the best solution/workaround for every browser (including IE, Firefox, Chrome, etc).
You can see this answer, but if you don't like it, you can use box-sizing CSS3 property like this:
input {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
Live jsFiddle example
Padding adds to the width of your object. One option would be to remove the left/right padding from the input and just use text-indent, although this removes the right padding.
.inside{
background: blue;
border: none;
padding-bottom: 10px;
padding-top: 10px;
text-indent: 10px;
width: 100%;
}
Alternatively, instead of using hardcoded pixel-widths for your padding, you could use percentages, and subtract that value from the width:
.inside{
padding: 3%;
width: 94%;
}
Don't specify the width of the inside div as 100%. A div will automatically fit the width of its parent container. Demo
Looks like the input is inside the div but is located in the top left corner. Because the input takes-up 100% of the div's width it obscures the red background of the div. The div is longer so it sticks out the bottom making it seem like the input is on-top. Do the following:
Apply the padding to the CSS of the outside div not the input box.
You could apply a margin to the input if you want but I think padding
the containing div is better.
Make the input box less wide than the div (<100%)