HTML extend height of div - html

div.div1 {
position: relative;
border: 1px solid black;
height: 100px;
width: 100px;
padding: 10px;
}
div.div2 {
background-color: gray;
border: 1px solid black;
padding: 10px;
}
div.div3 {
position: absolute;
border: 1px solid red;
height: 20px;
width: 20px;
bottom: 10px;
left: 10px;
}
<div class="div1">
<div class="div2">Test 123</div>
<div class="div3">A</div>
</div>
I use the above code to display a big div with two divs in it. For the first one I use position: absolute to place it on bottom left of the div.
How can I extend the height of the second gray one so that it's 5 pixels above the first, but without having to measure its exact height in pixel (like the pic below)? I can set height: 50px; for example but is there another way?

I would use a flexbox approach rather than absolute positioning (comments in css below)
div.div1 {
display: flex;
flex-direction:column;
/* add the above styles*/
border: 1px solid black;
min-height: 100px; /*I would also change this to min-height otherwise it may cause issues if your text goes to 2 lines*/
width: 100px;
padding: 10px;
}
div.div2 {
flex-grow:1; /* make div grow to fill the space */
margin-bottom:5px; /* minus the amount of margin you wanted */
background-color: gray;
border: 1px solid black;
padding: 10px;
}
div.div3 {
/* remove absolute positioning */
border: 1px solid red;
height: 20px;
width: 20px;
}
<div class="div1">
<div class="div2">Test 123</div>
<div class="div3">A</div>
</div>

EDIT: I suggest that, if you can focus on the modern browser features, going the flexbox way as shown by Pete is definitely a cleaner approach than the ones I've shown bellow. That being said, here are the alternatives:
You can use calc to dynamically determine the height of div2:
div.div1 {
position: relative;
border: 1px solid black;
height: 100px;
width: 100px;
padding: 10px;
}
div.div2 {
background-color: gray;
border: 1px solid black;
padding: 10px;
height: calc(
100%
- 20px /* div1: padding top and bottom */
- 2px /* div1: border top and bottom */
- 20px /* div3: height */
- 2px /* div3: border top and bottom*/
- 5px /* desired separation*/
);
}
div.div3 {
position: absolute;
border: 1px solid red;
height: 20px;
width: 20px;
bottom: 10px;
left: 10px;
}
<div class="div1">
<div class="div2">Test 123</div>
<div class="div3">A</div>
</div>
You can avoid including padding and border width in your calculations if you set the box-sizing for your divs to border-box (You might want to set this for all elements):
div {
box-sizing: border-box;
}
div.div1 {
position: relative;
border: 1px solid black;
height: 100px;
width: 100px;
padding: 10px;
}
div.div2 {
background-color: gray;
border: 1px solid black;
padding: 10px;
height: calc(
100%
- 20px /* div3: height */
- 5px /* desired separation */
);
}
div.div3 {
position: absolute;
border: 1px solid red;
height: 20px;
width: 20px;
bottom: 10px;
left: 10px;
}
<div class="div1">
<div class="div2">Test 123</div>
<div class="div3">A</div>
</div>

There's this rather new, hip CSS property called 'flex' which you're now going to love because it does it exactly that without the need of positioning absolute etc. I did something similar yesterday where I had a vertical nav bar and I wanted one menu at the top and one at the bottom. In a responsive environment; using your approach of positioning absolute it would've resulted in a nasty mess of working out heights to stop the content from overlapping. Flex prevented this! Yeyyyyy
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
In your example you want to do something like this:
.div1 {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: space-around;
}
.div2 {
align-self: flex-start;
flex-grow:1;
width:100%;
}
.div3 {
align-self: flex-end;
width:100%;
}
Now your div 3 will always be at the bottom. Although now .div3 will extend the entire width so within the div insert your content and BOOM done.

You can use calc on the heightsetting as in my snippet below. That setting is 100% minus (20 + 10 + 2) for the height, border and bottom of the lower DIV minus (5 + 2) for the distance and the border of the first DIV minus 10px for the padding of the parent, summing up to 49px .
div.div1 {
position: relative;
border: 1px solid black;
height: 100px;
width: 100px;
padding: 10px;
}
div.div2 {
background-color: gray;
border: 1px solid black;
padding: 10px;
height: calc(100% - 49px);
}
div.div3 {
position: absolute;
border: 1px solid red;
height: 20px;
width: 20px;
bottom: 10px;
left: 10px;
}
<div class="div1">
<div class="div2">Test 123</div>
<div class="div3">A</div>
</div>

Related

Two borders overlapping with different sizes

Is there any better way of setting two borders like in the example below? I could only do it with positioning. I'm new here so I apologize for any mistakes whatsoever.
.border1 {
margin: 0 auto;
height: 300px;
width: 250px;
border: 9px solid red;
position: relative;
}
.border2 {
border: 9px solid blue;
height: 250px;
width: 300px;
position: absolute;
top: 12px;
left: -33px;
}
<div class="border1">
<div class="border2"></div>
</div>
Absolute is indeed a good and easy way here.
You can also use a pseudo and only coordonates to size the second border box.
.border1 {
margin: 0 auto;
min-height: 150px;/* allow it to grow */
width: 250px;
padding:20px 0.5em;
border: 9px solid red;
position: relative;
}
.border2:before {
content:'';
border: 9px solid blue;
pointer-events:none;/* to allow clicking through else you may use a negative z-index */
position: absolute;
top: 12px;
bottom:12px;
left: -33px;
right:-33px;
}
<div class="border1 border2">
add anything here instead setting height
</div>
This is a different approach. I used box-shadow as the second border and you will no longer need a second div for second border.
.border{
margin:0 auto;
height:300px;
width:250px;
border:9px solid red;
position:relative;
box-shadow: 0 0 0px 9px blue;
}
<div class="border"></div>
You can do it with the Flexbox and without unnecessary calculations:
.border1 {
margin: 0 auto;
height: 300px;
width: 250px;
border: 9px solid red;
display: flex; /* displays flex-items (children) inline */
justify-content: center; /* centers them horizontally */
align-items: center; /* and vertically */
}
.border2 {
flex: 0 0 300px; /* doesn't shrink, flex-basis set to "300px" (initial width) */
border: 9px solid blue;
height: 250px;
}
<div class="border1">
<div class="border2"></div>
</div>

Why does my position: absolute child overflow my parent's border?

I have a parent container, with some child components inside. The last child has to be placed at the bottom of the container. I tried using justify-content: space-between, but it doesn't work for me because I need that the space between the last element and the other elements is greater and noticeable. I ended up trying position:absolute, bottom: 0, but the width of the child is greater than the parent.
Perhaps there's a better way to do it by mixing with flex, just haven't been able to do it.
.Parent {
background: #F8F8F8;
height: 400px;
padding: 20px;
width: 395px;
position: relative;
max-width: 395px;
border: solid 1px red;
}
.First--Child {
border: solid 1px blue;
height: 40px;
margin: 10px 0;
}
.Second--Child {
border: solid 1px green;
height: 40px;
margin: 10px 0;
}
.Third--Child {
border: solid 1px violet;
height: 40px;
margin: 10px 0;
}
.Last--Child {
border: solid 1px cyan;
height: 60px;
position: absolute;
bottom: 0;
width: 100%;
margin: 0 0 10px 0;
display: flex;
justify-content: space-between;
}
.Left--Button,
.Right--Button {
border: solid 1px gray;
width: calc(100% - 300px);
}
<div class='Parent'>
<div class='First--Child'>
</div>
<div class='Second--Child'>
</div>
<div class='Third--Child'>
</div>
<div class='Last--Child'>
<button class='Left--Button'>Left</button>
<button class='Right--Button'>Right</button>
</div>
</div>
The width of the last child isn't wider than the parent - its the same width. It is the margin that has caused it to be out of alignment.
If the bottom placement is correct for your needs, you could get the horizontal alignment sorted either by removing the padding on the parent, setting the child to:
left: -20px
or
margin-left: -20px
, or adding
box-sizing:border-box
to the parent
If you must use this layout technique, you could calculate the last--child's width minus the padding of the parent.
.Parent {
background: #F8F8F8;
height: 400px;
padding: 20px;
width: 395px;
position: relative;
max-width: 395px;
border: solid 1px red;
}
.First--Child {
border: solid 1px blue;
height: 40px;
margin: 10px 0;
}
.Second--Child {
border: solid 1px green;
height: 40px;
margin: 10px 0;
}
.Third--Child {
border: solid 1px violet;
height: 40px;
margin: 10px 0;
}
.Last--Child {
border: solid 1px cyan;
height: 60px;
position: absolute;
bottom: 0;
width: calc(100% - 40px);
margin: 0 0 10px 0;
display: flex;
justify-content: space-between;
}
.Left--Button,
.Right--Button {
border: solid 1px gray;
width: calc(100% - 300px);
}
<div class='Parent'>
<div class='First--Child'>
</div>
<div class='Second--Child'>
</div>
<div class='Third--Child'>
</div>
<div class='Last--Child'>
<button class='Left--Button'>Left</button>
<button class='Right--Button'>Right</button>
</div>
</div>
Try this for your CSS. I split the buttons into two classes and just floated them while adding a height percentage for the fill. This is assuming you are okay with absolute positioning.
.Parent {
background: #F8F8F8;
height: 400px;
padding: 20px;
width: 395px;
position: relative;
max-width: 395px;
border: solid 1px red;
}
.First--Child {
border: solid 1px blue;
height: 40px;
margin: 10px 0;
}
.Second--Child {
border: solid 1px green;
height: 40px;
margin: 10px 0;
}
.Third--Child {
border: solid 1px violet;
height: 40px;
margin: 10px 0;
}
.Last--Child {
border: solid 1px cyan;
height: 60px;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
display: block;
justify-content: space-between;
}
.Left--Button {
height:100%;
float:left;
border: solid 1px gray;
width: calc(100% - 300px);
}
.Right--Button {
height: 100%;
float: right;
border: solid 1px gray;
width: calc(100% - 300px);
}
The last child has to be placed at the bottom of the container. I tried using justify-content: space-between, but it doesn't work for me because I need that the space between the last element and the other elements is greater and noticeable.
With justify-content: space-between (in a vertical container) or align-content: space-between (in a horizontal container) you can pin the last item to the bottom, and not impact the siblings' position, only if there are two items (one stays on top, the other stays at the bottom).
But if there are more than two items, then this method will not work because space-between distributes space evenly between items, causing the items between the first and last to spread out.
Since you have more than two items in your container, you need another method.
Absolute positioning indeed works. It pins the last item to the bottom. However, it also removes the item from the normal flow, meaning that it doesn't take up space and siblings can overlap it.
Flexbox, however, provides a clean and efficient alternative: auto margins. By setting the last item to margin-top: auto, it shifts to the bottom of the container, while its siblings remain at the top.
Here's a complete explanation, which includes a comparison of space-between and auto margins:
In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?
.Parent {
display: flex; /* new */
flex-direction: column; /* new */
height: 400px;
padding: 20px;
max-width: 395px;
border: solid 1px red;
background: #F8F8F8;
}
.First--Child {
border: solid 1px blue;
height: 40px;
margin: 10px 0;
}
.Second--Child {
border: solid 1px green;
height: 40px;
margin: 10px 0;
}
.Third--Child {
border: solid 1px violet;
height: 40px;
margin: 10px 0;
}
.Last--Child {
border: solid 1px cyan;
height: 60px;
margin: auto 0 10px 0; /* adjustment to margin-top */
display: flex;
justify-content: space-between;
}
.Left--Button,
.Right--Button {
border: solid 1px gray;
width: calc(100% - 300px);
}
<div class='Parent'>
<div class='First--Child'></div>
<div class='Second--Child'></div>
<div class='Third--Child'></div>
<div class='Last--Child'>
<button class='Left--Button'>Left</button>
<button class='Right--Button'>Right</button>
</div>
</div>

Using CSS, how do you anchor an element to a baseline and size it based on another "pinned" element?

Here's an image of what I'm referring to:
If you have some fixed height h from the baseline that the pin lies, and the green element is dynamically sized, how can you make the orange element take the space between the two?
Have exactly what you need in this case using a flexbox.
The pin approximately stays at the same height above the baseline give or take 1px.
How it works: When the green element grows say 10px the pin is elevated by 5px. But the flex setup means the dummy and the orange box reduces 5px each thus keeping the pin at a contant height.
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
}
.wrapper {
display: flex;
flex-direction: column;
align-items: center;
height: 100px;
border-bottom: 1px solid black;
}
.dummy {
flex: 1;
}
.top {
height: 20px;
width: 20px;
border: 1px solid green;
position: relative;
}
.top div {
position: absolute;
height: 3px;
width: 3px;
background: #880015;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.bottom {
width: 50px;
border: 1px solid orange;
flex: 1;
}
<div class="wrapper">
<div class="dummy"></div>
<div class="top">
<div></div>
</div>
<div class="bottom"></div>
</div>
You can use table properties for this. Table cells fill its parent width. If one cell is short, the other one will expand to fill its parent. The trick here is to rotate 90ยบ your "table" and it's done. To change the 'height" of your pinned item you will actually be changing its width. The anchor element will resize accordingly.
Be aware of this though: http://caniuse.com/#search=transform
.baseline{
height: 100px;
width: 100px;
border: 3px solid black;
display: table;
transform: rotate(90deg);
}
.pinned,.anchored{
display: table-cell;
}
.pinned{
width: 30px;
border: 3px solid green;
}
.anchored{
border: 3px solid orange;
}
<div class="baseline">
<div class="pinned">
</div>
<div class="anchored">
</div>
</div>

Setting up textarea to consume all the available space in a div (minus N pixels at the top)

I am trying to set up a custom toolbar for a textarea, I have the following
html:
<div id="main">
<div id="toolbar"></div>
<textarea></textarea>
</div>
css:
#main {
background-color: #ddd;
height: 400px;
width: 400px;
position: relative;
}
#toolbar {
background-color: #444;
height: 40px;
color: white;
}
textarea {
outline: none;
border: none;
border-left: 1px solid #777;
border-right: 1px solid #777;
border-bottom: 1px solid #777;
margin: 0;
position: absolute;
top: 40px;
bottom: 0;
left: 0;
right: 0;
}
It works exactly as I expected in Chrome, but in firefox / ie the text area is not consuming all the available space in the div.
How do I set it up so the toolbar takes up 40px at the top of the div, and the textarea consumes all the rest of the height.
I am sizing this stuff dynamically so can not use a "px" height or width for the textarea.
Codepen here: http://codepen.io/anon/pen/pDgvq
Better Suggestion
Set the textarea's width and height to 100%. Then, give it a 40px top-border that is transparent (color doesn't really matter, actually). Be sure to set box-sizing to border-box. Now position the relative toolbar on a higher z-index - voila.
Pen: http://codepen.io/anon/pen/nFfam
Oldie
Rather than moving the textarea down, move the toolbar up:
#main {
background-color: #ddd;
height: 200px; width: 400px;
position: relative;
top: 40px;
}
#toolbar {
background-color: #444;
height: 40px; width: 100%;
position: absolute;
top: -40px;
}
textarea {
width: 100%; height: 100%;
box-sizing: border-box;
}
Pen: http://codepen.io/anon/pen/mEGyp
Both Firefox and IE9+ support the calc() CSS function (you're out of luck with IE8 though; not sure what you're supporting).
I've added these lines to the textarea's CSS in your pen (updated version):
width: calc(100% - 2px);
height: calc(100% - 41px);
padding: 0;
The padding is just for normalization; you can choose whatever suits your needs, but be sure to adjust the pixel values in calc() accordingly. The 2px for width are to compensate the left and right border; the 41px for height are 40 for the toolbar and 1 for the bottom border.
Add width:-moz-available; height:100%;resize: none; to textarea
textarea {
outline: none;
border: none;
border-left: 1px solid #777;
border-right: 1px solid #777;
border-bottom: 1px solid #777;
margin: 0;
position: absolute;
top: 40px;
bottom: 0;
left: 0;
right: 0; width:-moz-available; height:100%;
resize: none;
}
UPDATED DEMO
Another Method
You can add a div around textarea and give position:absolute to the div
HTML
<div id="main">
<div id="toolbar"></div>
<div id="container">
<textarea></textarea>
</div>
</div>
CSS
#container{
position:absolute;
bottom:0px;
top:40px;
width:100%
}
textarea {
outline: none;
border: none;
border-left: 1px solid #777;
border-right: 1px solid #777;
border-bottom: 1px solid #777;
resize: none; height:100%; width:99.5%
}
DEMO 2
You can use height and width for textarea in % also apply top to the toolbar div in %
e.g. If top is 10% give 90% height to textarea.
I hope this is your desired result: Demo
#main {
background-color: #ddd;
width: 400px; height: 200px;
padding: 0;
}
div #toolbar {
background: #444;
width: 100%; height: 40px;
}
textarea {
margin: 0;
width: 100%; height: 100%;
}

Left-bottom border

Imagine (or if you can't imagine, watch) this piece of code:
<div class="block"></div>
<style>
.block {
width: 10px;
height: 10px;
display: block;
background-color: red;
border: 1px solid #000000;
border-bottom: 0;
}
</style>
Now look at the bottom line. This is my problem; I want the left and right border to be 1px longer (so the bottom border is the part between the left border and right border).
Is it possible to accomplish this??
This is a way to do it, since the box model does not support what you need, using only one div:
<div class="block"><div></div></div>
and the css:
.block {
width: 10px;
height: 10px;
border: 1px solid #000000;
border-bottom: 0;
padding-bottom: 1px;
}
.block div {
width: 10px;
height: 10px;
background-color: red;
}
This will extend the black border on the left and right side with 1px.
Try this :)
http://jsfiddle.net/z6ASC/
This is possible if you have two containers, one for the outside left/right borders, and one for the inside bottom-border. I've put together a demo showing this.
DEMO:
http://wecodesign.com/demos/stackoverflow-7074782.htm
<style type="text/css">
#borderOutside {
height: 200px;
width: 300px;
border:1px solid #900;
border-bottom: none;
padding-bottom: 5px; /*this is the gap at the bottom*/
}
#borderInside {
height: 100%;
border-bottom: 1px solid #900;
}
</style>
<div id="borderOutside">
<div id="borderInside"><!--Your Content--></div>
</div>
It can be done without adding any extraneous elements in your HTML via this strategy:
.block {
position: relative;
width: 10px;
height: 10px;
display: block;
background-color: red;
}
.block:before {
position: absolute;
content: '';
width: 10px;
height: 11px;
top: -1px;
left: -1px;
border: 1px solid #000;
border-bottom: none;
}
The pseudo element :before is only supported from IE8, but works in all other major browsers.