CSS - div extend height to match sibling - html

The code below gives this result:
Which is very close to the result I want except three facts:
Why is there a very odd grey area at the bottom of the picture?
How can I make the orange div extend to the bottom of the picture? I tried height: 100% but it didn't work...
How can I also give a 10 pixels space between the div of the text and the picture?
Desired result:
div.div1 {
background-color: yellow;
border: 1px solid black;
padding: 10px;
overflow: auto;
}
div.div2 {
border: 1px solid gray;
float: right;
}
div.div3 {
background-color: orange;
border: 1px solid gray;
height: 100%;
padding: 10px;
}
<div class="div1">
<div class="div2">
<img src="http://splendidwillow.com/wp-content/uploads/2012/04/Allium-Purple-garlic-flowers-200x200.jpg">
</div>
<div class="div3">
Text about flowers
</div>
</div>

div.div1 {
display: flex; /* 1 */
padding: 10px;
overflow: auto;
background-color: yellow;
border: 1px solid black;
}
div.div2 {
order: 1; /* 2 */
border: 1px solid gray;
}
div.div3 {
flex: 1; /* 3 */
margin-right: 10px;
padding: 10px;
/* height: 100% */ /* 4 */
background-color: orange;
border: 1px solid gray;
}
img {
vertical-align: bottom; /* 5 */
}
<div class="div1">
<div class="div2">
<img src="http://splendidwillow.com/wp-content/uploads/2012/04/Allium-Purple-garlic-flowers-200x200.jpg">
</div>
<div class="div3">
Text about flowers
</div>
</div>
Notes:
Establish flex container. By default, children will line-up in a row (flex-direction: row) with equal height (align-items: stretch).
Make image appear last in visual display (default order value for all flex items is 0)
Make orange box consume all available space in the row.
Remove defined heights on flex items. They will override align-items equal height feature.
Mystery white space underneath image tag

Surely img's margin-bottom, set it to 0.
Flexbox surely is your friend here.
Same as 1, but with margin-left in img and margin-right in .div2, both of 5.

Related

Vertical line between two divs?

I have a problem with positioning the vertical line. Here's the project:
https://prnt.sc/wp2vh4
div class="col span-1-of-2"
to separate those two lists BUT - there's a grey vertical line in the 'center' between them. When I make border-right for the first div, it's way too on the right side. How can I make this line more in the center?
two elements are block - should it be something connected to that? but I don't want to 'ruin' the column system.
You could essentially take the two columns and give them a box-shadow of a half pixel each (totaling to 1px side by side). Half pixels don't work with border declarations reason being.
.container {
display: flex;
height: 150px;
}
.col {
align-items: center;
display: flex;
flex: 1;
justify-content: center;
}
.left {
box-shadow: .5px 0 0 #000;
}
.right {
box-shadow: -.5px 0 0 #000;
}
<div class="container">
<div class="col left">Left</div>
<div class="col right">Right</div>
</div>
  
There are a lot of ways to do this, another solution would be using the old columns css property, like this
.container {
columns: 2;
column-gap: 0;
column-fill: balance;
column-rule: 2px solid #ff44cc;
text-align: center;
padding: 10px;
}
<div class="container">
<div>Block</div>
<div>Block</div>
</div>
Take the solution that mosts suits you.
There are many ways to accomplish a vertical divider between columns.
Option #1
The easiest is to utilize CSS flex-box to create the columns. This will cause both columns to be the same height in the container and you can use a border to create the visual divider.
/* this section illustrates the container sizes */
#container {
border: 1px dashed #dadada;
padding: 2px;
}
.col {
padding: 20px;
font-family: Helvetica, Arial, Sans-serif;
background: tan;
border: 1px dashed #333;
}
/* this shows the solution */
#container {
display:flex;
justify-content: space-between;
}
.col {
flex-basis: 50%;
}
.col:first-child {
border-right: 3px solid aqua;
}
<div id="container">
<div class="col">Column 1</div>
<div class="col">Column 2 with lots of content that makes it much taller than the other column and messes with heights.</div>
</div>
Option #2
Use a pseudo element on the parent container to create a border.
/* this section illustrates the container sizes */
#container {
border: 1px dashed #dadada;
padding: 2px;
}
.col {
padding: 20px;
font-family: Helvetica, Arial, Sans-serif;
background: tan;
border: 1px dashed #333;
}
/* The solution */
#container {
position: relative;
overflow: auto;
}
#container:before {
content: '';
width: 2px;
background: aqua;
position: absolute;
top: 0;
left: 50%;
bottom: 0;
transform: translateX(-50%);
}
.col {
float:left;
width: calc(50% - 42px);
/* need to remove the border & padding width from the full width */
}
<div id="container">
<div class="col">Column 1</div>
<div class="col">Column 2 with lots of content that makes it much taller than the other column and messes with heights.</div>
</div>
Option #3
Really there are lots more options, a CSS gradient background, shadows, CSS Grid, CSS Columns, this list goes on.

HTML extend height of div

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>

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>

Stack divs vertically with different child alignment

http://s4.postimg.org/mbrpxn2d9/Untitled.png
Edit: Not a duplicate. The other question doesn't contain information about divs being automatically adjusted to the words on the inside.
I have 4 divs. I have 3 divs inside another div, and I'm trying to float one to the left, one to the center, and one to the right. I'm also trying to make the width and height of the divs on the inside to be automatically adjusted to the width and height of the words on the inside of the divs. I also want the divs on the inside to stack up on top of each other, instead of being on the same line. So far, I got the left div to float to the left, and the right div to float to the right, but I just cannot get the middle div to be centered, nor get it to adjust to the width and height of the word inside of it. Please take a look at my code:
#outer {
border: 1px solid black;
width: 500px;
height: 500px;
}
#innerLeft {
border: 1px solid red;
float: left;
}
#innerMiddle {
border: 1px solid red;
margin: auto;
}
#innerRight {
border: 1px solid red;
float: right;
}
<div id='outer'>
<div id='innerLeft'>Left</div>
<div id='innerMiddle'>Middle</div>
<div id='innerRight'>Right</div>
</div>
Depending on the output of the image, I think flexbox solution would be a good way to go.
Let the container have a flexible layout with column wrapping.
Align each item based on position in the container i.e. flex-start, center and flex-end
#outer {
display: flex;
display: -ms-flex;
flex-flow: column wrap; /* Wrap the items column wise */
justify-content: flex-start; /* Items to start from the top of the container */
border: 1px solid black;
width: 500px;
height: 500px;
}
#innerLeft {
align-self: flex-start; /* Equivalent to float: left of your code */
border: 1px solid red;
}
#innerMiddle {
align-self: center; /* Equivalent to margin: auto */
border: 1px solid red;
}
#innerRight {
align-self: flex-end; /* Equivalent to float: right */
border: 1px solid red;
}
<div id='outer'>
<div id='innerLeft'>Left</div>
<div id='innerMiddle'>Middle</div>
<div id='innerRight'>Right</div>
</div>
If changing your HTML just a bit is an option, you can add span elements in your divs which will give you want, and it will work in all browsers:
#outer {
border: 1px solid black;
width: 500px;
height: 500px;
}
#innerLeft {
text-align:left;
}
#innerMiddle {
text-align:center;
}
#innerRight {
text-align:right;
}
div > div > span {
border: 1px solid red;
}
<div id='outer'>
<div id='innerLeft'><span>Left</span></div>
<div id='innerMiddle'><span>Middle</span></div>
<div id='innerRight'><span>Right</span></div>
</div>
This is what you mean?? I had Edited
#outer {
border: 1px solid black;
width: 500px;
height: 500px;
}
#innerLeft {
border: 1px solid red;
/* width: 30%; */
float: left;
}
#innerMiddle {
border: 1px solid red;
float: left;
margin: 0 5px;
}
#innerRight {
border: 1px solid red;
float: right;
}
<div id='outer'>
<div id='innerLeft'>LeftLeftLeftLeft</div> <br>
<div id='innerMiddle'>MiddleMiddleMiddleMiddle</div> <br>
<div id='innerRight'>RightRightRightRight</div>
</div>
write your html tags like this hope it help!
<div id='outer'>
<div id='innerRight'>Right</div>
<div id='innerLeft'>Left</div>
<div id='innerMiddle'></div>
</div>

Dynamically size block element when overlapped by float

Given a block element and a float that sits to the right of it, how can I ensure the block element doesn't overlap the float when space is constrained? Here's an example (jsfiddle):
HTML:
<body>
<div class='goodContainer'>
<div class='floater'>Image Placeholder</div>
<p class='header'>Header is here</p>
</div>
<br/>
<div class='badContainer'>
<div class='floater'>Image Here</div>
<p class='header'>Header is here</p>
</div>
</body>
CSS:
.goodContainer {
width: 400px;
border: 1px solid green;
}
.badContainer {
width: 300px;
border: 1px solid red;
}
.header {
border: 1px solid black;
max-width: 70%;
}
.floater {
float: right;
width: 100px;
height: 100px;
border: 1px solid blue;
}
In the first box (green border) there's enough space to allow the header and image to coexist peacefully. In the second (red box) space starts to get constrained and they begin to overlap. Is there any way I can make the header resize dynamically in this case as to not overlap the image? I'm open to changing whatever is needed to make it work while keeping the general appearance (specifically that it preserves the proper width of the header when available).
Perhaps this one:
.header {
display: block;
margin: 5px 0px;
border: 1px solid black;
margin-right: 100px;
max-width: 250px;
}
http://jsfiddle.net/5bpgrcq9/6/