Div position of "button" depends on content height - html

I'm working on the sidebar where we have a logo at the top and some bottom div. The middle div "content" has overflow: scroll and contains paragraph(s). So what I need... If I have only one paragraph (or two p) the button div should be positioned absolutely at the bottom of the content and if I have more paragraphs which have a bigger height than "content" div so then the button div will have position static (so will be scrollable).
And I need it only by CSS. Is it possible?
We need IE11+ support.
<div class="sidebar">
<div class="logo">logo</div>
<div class="content">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam tempor egestas ornare. Suspendisse potenti. Integer non euismod nulla. Quisque pretium est sit amet congue rhoncus.</p>
<div class="button">
Button
</div>
</div>
<div class="bottom"></div>
</div>
.sidebar {
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 300px;
background-color: grey;
}
.logo {
position: absolute;
width: 100%;
height: 55px;
background-color: red;
}
.bottom {
position: absolute;
bottom: 0;
width: 100%;
height: 100px;
background-color: green;
}
.content {
position: absolute;
top: 55px;
bottom: 100px;
overflow-y: scroll;
}
.button {
display: inline-block;
padding: 1em 0 1em;
text-align: center;
width: 100%;
border-radius: 50px;
background-color: white;
}

You can use flexbox. Add this to your CSS:
.content {
display:flex;
flex-wrap: wrap;
}
.button {
align-self: flex-end;
}
That will render the button always at the end of the content div.

Related

Text overflows into other div when window is resized

I have multiple divs that are stacked in a vertical fashion but when I resize the window the text from one div overflows into other divs and all text on the page becomes unreadable because they are all overlaying eachother. Is it possible to make it so that when the window is resized instead of divs overflowing into eachother they instead expand their height so they are stacked on top of eachother?
Here's my CSS
.middle {
height: 100%;
width: 65%;
position: relative;
top: 74px;
margin: auto;
}
.middle .portSection {
position: relative;
display: inline-block;
width: 100%;
height: 450px;
}
.middle .portSection .left {
position: absolute;
height: 100%;
width: 50%;
left: 0px;
}
.middle .portSection .right {
position: absolute;
height: 100%;
width: 50%;
right: 0px;
}
.middle .portSection .left .description {
position: relative;
height: auto;
width: 100%;
font-size: 30px;
}
".middle" is what holds all of the divs, ".middle .portSection .left .description" is the p element that is overflowing
Most of your css seems redundant here. By using position absolute you are removing the elements from the document flow.
I recommend you instead use flexbox as it's much better designed to handle this type of layout.
.middle .portSection {
display: flex;
height: 450px;
}
.middle .portSection .left {
background: #f88;
flex:1;
}
.middle .portSection .right {
background: #88f;
flex:1;
}
.middle .portSection .left .description {
font-size: 30px;
}
<div class="middle">
<div class="portSection">
<div class="left">
</div>
<div class="right">
<p class="description">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla congue nisi pellentesque, consectetur tellus sit amet, convallis sem. Pellentesque in ante mauris. Quisque sodales ex sagittis, eleifend tellus eget, iaculis risus. Aenean imperdiet risus
eu lacus varius, non auctor tortor vehicula. Phasellus sed augue in neque auctor tempor. Cras bibendum mauris velit, id rhoncus diam fermentum eget. Proin quis condimentum nisl. Fusce consequat augue ullamcorper, ornare felis quis, volutpat mauris.
</p>
</div>
</div>
</div>
try adding this to your styles
.left .description {
max-width: 100%;
}
Or,
.left .description p {
word-wrap: break-word;
}
Try
.middle .portSection .left .description {
position: relative;
height: 100%;
width: 100%;
font-size: 30px;
}
It should work :)
.middle {
height: fit-content;
width: 65%;
position: absolute;
top: 74px;
margin: auto;
}
.middle .portSection {
position: relative;
display: inline-block;
width: 100%;
height: 450px;
}
.middle .portSection .left {
position: absolute;
height: 100%;
width: 50%;
left: 0px;
}
.middle .portSection .right {
position: absolute;
height: 100%;
width: 50%;
right: 0px;
}
.middle .portSection .left .description {
position: absolute;
margin: 10px 0;
padding: 2px 0;
height: max-content;
width: 100%;
font-size: 30px;
}
if this does not work, then please share your HTML also.
I can't understand what you want to explain but I some what figure out that you want to show two paragraphs side by side in middle. Right?
the problem caused because you user position absolute and relative as the div scale full display after adding position absolute and it is very difficult to figure out relative position for all child div if you are not well familiar with position properties. In this case I will suggest you to use flex-box. It will make your work easy as below :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Demo</title>
<style type="text/css">
*
{
padding: 0px;
}
.middle {
display: flex;
width: 65%;
margin: auto;
align-items: center;
height: 90vh;
}
.middle .portSection {
display: flex;
width: 100%;
height: 450px;
}
.middle .portSection .left {
background: grey;
display: flex;
width: 100%;
height: 100%;
padding: 5px;
}
.middle .portSection .right {
background: grey;
display: flex;
width: 100%;
height: 100%;
padding: 5px;
}
.middle .portSection .left .description {
background: skyblue;
height: auto;
width: 100%;
font-size: 30px;
}
.middle .portSection .right .description {
background: skyblue;
height: auto;
width: 100%;
font-size: 30px;
}
</style>
</head>
<body>
<div class="middle">
<div class="portSection">
<div class="left">
<p class="description">Here is a div1 sddfsdafdsfdsf ds dsfds s fdsaf sdf dsf sdfds fdsf d fdf dsf ds fdsfds fdsf dsa f dsa fda</p>
</div>
</div>
<div class="portSection">
<div class="right">
<p class="description">Here is a div2 sddfsdafdsfdsf ds dsfds s fdsaf sdf dsf sdfds fdsf d fdf dsf ds fdsfds fdsf dsa f dsa fda</p>
</div>
</div>
</div>
</body>
</html>

Shrink Image to fit flex column

I have a image that I would like to shrink in a flexbox column layout. I have read a bunch of pertinent threads but I still can't figure it out.
I want the right column to always have the same height of the left column and the image in the right column to fill the height of the remaining space not taken up by the text. Any thoughts? Thank you!
I would like it to look like this:
Codepen here: https://codepen.io/interzonestudio/pen/qBRPxzg
This is my HTML:
<div class="block-one">
<div class="block-one-left">
<img src="https://via.placeholder.com/300x400" alt="">
</div>
<div class="block-one-right">
<div class="block-one-right-top">
<img src="https://via.placeholder.com/300x400?text=Shrink+Me!" alt="">
</div>
<div class="block-one-right-bottom">
<p>Lorem ipsum dolor sit amet, consectetuer diiscing elit, sed diam nonummy nibh dolor it euismod tincidunt ut laoreet dolore.</p>
</div>
</div>
</div>
and this is my CSS:
.block-one {
width: 50%;
padding: 50px;
background: #9ac1e4;
margin: 0 50px 100px 50px;
display: flex;
min-height: 0;
min-width: 0;
max-width: 100%;
max-height: 100%;
}
.block-one-left {
width: 40%;
padding-right: 50px;
}
.block-one-left img {
width: 100%;
}
.block-one-right {
width: 60%;
display: flex;
flex: 1;
flex-direction: column;
}
.block-one-right-top {
height: 100%;
flex: 1;
}
.block-one-right-top img {
height: 100%;
max-width: 100%;
max-height: 100%;
min-height: 0;
min-width: 0;
width: auto;
object-fit: contain;
}
You can achieve this with a tiny piece of javascript to calculate the difference of left img height minus text height and set the right image height to that difference. Just place these 4 lines javascript in a <script></script>-tag just before the closing body tag.
Working example:
var max_height = document.querySelector('.block-one-left').clientHeight;
var text_height = document.querySelector('.block-one-right-bottom').clientHeight;
var shrink_height = max_height - text_height;
document.querySelector('.block-one-right-top').style.height = shrink_height + 'px';
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.block-one {
display: flex;
width: 600px;
margin: 0 50px 100px 50px;
padding: 25px;
background: #9ac1e4;
}
.block-one-left {
height: 300px;
margin-right: 25px;
}
.block-one-left img {
height: 100%;
}
.block-one-right {
width: 225px;
}
.block-one-right-top img {
height: 100%;
}
.block-one-right-bottom {
padding-top: 25px;
}
<div class="block-one">
<div class="block-one-left">
<img src="https://via.placeholder.com/300x400" alt="">
</div>
<div class="block-one-right">
<div class="block-one-right-top">
<img src="https://via.placeholder.com/300x400?text=Shrink+Me!" alt="">
</div>
<div class="block-one-right-bottom">
<p>Lorem ipsum dolor sit amet, consectetuer diiscing elit, sed diam nonummy nibh dolor it euismod tincidunt ut laoreet dolore.</p>
</div>
</div>
</div>
If you want it to be responsive you have to wrap the 4 lines in a function. Because you have to listen for at least two events (image loaded and window resized) it is much cleaner to call the function instead of having the 4 lines twice in your code.
Working example:
var left_img = document.querySelector('.block-one-left img');
function setHeight() {
var max_height = left_img.clientHeight;
var text_height = document.querySelector('.block-one-right-bottom').clientHeight;
var shrink_height = max_height - text_height;
document.querySelector('.block-one-right-top').style.height = shrink_height + 'px';
}
left_img.addEventListener('load', setHeight);
window.addEventListener('resize', setHeight);
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.block-one {
display: flex;
width: 100%;
padding: 25px;
background: #9ac1e4;
}
.block-one-left {
width: 40%;
margin-right: 25px;
}
.block-one-left img {
width: 100%;
}
.block-one-right {
width: 50%;
}
.block-one-right-top img {
height: 100%;
}
.block-one-right-bottom {
padding-top: 25px;
}
<div class="block-one">
<div class="block-one-left">
<img src="https://via.placeholder.com/300x400" alt="">
</div>
<div class="block-one-right">
<div class="block-one-right-top">
<img src="https://via.placeholder.com/300x400?text=Shrink+Me!" alt="">
</div>
<div class="block-one-right-bottom">
<p>Lorem ipsum dolor sit amet, consectetuer diiscing elit, sed diam nonummy nibh dolor it euismod tincidunt ut laoreet dolore.</p>
</div>
</div>
</div>

How to make child element overlay the parent element?

I am using only CSS and Flexbox to build a responsive page. I have a child element that should "overflow" outside the parent element as shown here:
<div class="container-hero">
<div class="hero-content">
<h1>Tech Challenge</h1>
<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit </p>
</div>
<div class="hero-img">
<img src="assets/image-1.jpg">
</div>
</div>
CSS
.container-hero {
display: flex;
justify-content: flex-start;
align-items: center;
overflow: hidden;
position: relative;
margin: 40px 0;
}
.hero-img {
flex-shrink: 0;
min-width: 100%;
min-height: 100%;
}
.hero-img img {
width: 100%;
height: auto;
}
.hero-content {
background-color: #D64C31;
color: #FFFFFF;
align-self: flex-end;
width: 50%;
position: absolute;
bottom:0;
left:0;
padding: 40px 60px;
}
Any help would be appreciated!
Like that?
<html>
<head>
<style>
.container {
background: #ccc;
width: 50%;
margin: 0 auto;
position: relative;
height: 700px;
}
.overflowing-element {
background: red;
width: 200px;
height: 200px;
position: absolute;
right: -200px;
top: 0;
}
</style>
</head>
<body>
<div class="container">
test
<div class="overflowing-element">
bla
</div>
</div>
</body>
</html>
Just works with fixed width of that overflowing element, or with JavaScript.
EDIT: You just edited your images and now I don't know really what you mean :D
I figure it out, thank you for your help!
My parent element had an overflow: hidden I disabled it and adjusted the child element as follows:
bottom: -40px
If you have any feedback or this is considered a bad practice please let me know. I am just starting out here :)
.container-hero {
display: flex;
justify-content: flex-start;
align-items: center;
/* overflow-x: hidden; */
position: relative;
margin: 40px 0;
}
.hero-img {
flex-shrink: 0;
min-width: 100%;
min-height: 100%;
}
.hero-img img {
width: 100%;
height: auto;
}
.hero-content {
position:absolute;
background-color: #D64C31;
color: #FFFFFF;
width: 50%;
padding: 40px 60px;
bottom: -20px;
left:0;
}
</div>
<div class="container-hero">
<div class="hero-content">
<h1>Tech Challenge</h1>
<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit </p>
</div>
<div class="hero-img">
<img src="https://source.unsplash.com/800x300">
</div>
</div>
The property you are looking for is CSS Position.
Reference: CSS Position
.parent{
width:250px;
height: 20px;
background: yellow;
position:relative;
}
.child{
width:80px;
height: 100px;
background: purple;
position:absolute;
bottom: 0;
right:0;
}
<div class="parent">
<div class="child"></div>
</div>
Use the CSS positioning properties.
.container-hero {
position: relative; /* creates the container for absolutely positioned children */
}
.hero-content {
position: absolute;
bottom: -20px; /* use this offset to align vertically */
left: 20px; /* use this offset to align horizontally */
background-color: #D64C31;
color: #FFFFFF;
width: 225px;
padding: 40px 60px;
}
<div class="container-hero">
<div class="hero-content">
<h1>Tech Challenge</h1>
<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit </p>
</div>
<div class="hero-img">
<img src="https://via.placeholder.com/500x250.png?text=hero image">
</div>
</div>

3 column fixed header that expands height to fit content

I'm trying to create a fixed header at the top of my page that has 3 "columns". The first is left justified on the left side, the second is centered relative to the whole page - regardless of the other two column sizes, and the third is right justified, stuck on the right. I want all of the content centered vertically.
Floats didn't really work because then the middle column was not properly centered. So I used two position: absolute div's for the left and right, and just left one div in the middle.
My problem is that I can't get the header to expand to contain the left div, which is taller, and I can't get the content to center vertically.
What am I doing wrong? Thanks!
Here is my code:
.header {
z-index: 8;
top: 0;
left: 0;
position: fixed;
padding-top: 1rem;
padding-bottom: 1rem;
width: 100%;
background: white;
z-index: 8;
border-bottom: 1px solid black;
text-align: center;
}
.left {
position: absolute;
top: 1rem;
left: 1rem;
border: 1px solid gray;
background: red;
padding: 1rem;
height: 10rem;
}
.right {
position: absolute;
right: 1rem;
top: 1rem;
background: yellow;
border: 1px solid gray;
}
.middle {
background: green;
border: 1px solid gray;
}
<div class="header">
<div class="left">Left</div>
<div class="middle">MIDDLE......</div>
<div class="right">Right</div>
</div>
Here is the link to my fiddle.
I would suggest using a flexbox for the vertical alignment.
header {
display: flex;
justify-content: space-between;
align-items: center;
}
header>div {
padding: 1rem; /* To improve visibility */
width: calc(100% / 3);
}
.col1 {
text-align: left;
}
.col2 {
text-align: center;
}
.col3 {
text-align: right;
}
<header>
<div class="col1">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
<div class="col2">Lorem ipsum dolor sit amet, consectetur adipiscing elit...</div>
<div class="col3">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
</header>
Instead of the css that you have written, you can finish the above in just 8 lines. You just need to write the following:
.header{
display:flex;
}
.left, .middle, .right{
width: calc(100% / 3);
text-align:center;
}
and you can add the following class to check if everything is according what you planned to do:
*{
border: 1px solid red;
}
Here is the link to the fiddle displaying the result of the above code.
Check the result in the following stack overflow snippet:
* {
border: 1px solid red;
}
.header {
display: flex;
}
.left,
.middle,
.right {
width: calc(100% / 3);
text-align: center;
}
<div class="header">
<div class="left">Left</div>
<div class="middle">MIDDLE......</div>
<div class="right">Right</div>
</div>

Stick a Div element during Horizontal scroll

I am struggling with a layout problem and I hope to find some help to solve it.
I am designing a page with row/lane based content.
Each row has multiple div elements with some content.
So it has to be possible to scroll through the rows vertically as well as horizontally.
Now the problem is, that the first div element inside every row is kind of like the row header, which provides some description about the content of that row.
I want this div element to always stay visible during horizontal scrolling.
Position: fixed is not a option since it would prevent the "row-header" to scroll with its content during a vertical scroll.
What it should look like during a horizontal scroll
Here's the fiddle with my code: https://jsfiddle.net/rco56cbp/
html,
body {
font-family: 'Arial', sans-serif;
margin: 0;
}
* {
box-sizing: border-box;
}
header {
background: #F7F7F7;
box-shadow: 0px 2px 6px 0px rgba(0,0,0,0.50);
/**/
width: 100%;
height: 90px;
/**/
display: flex;
align-items: center;
justify-content: center;
position: fixed;
z-index: 55;
top: 0;
}
/* Left Sidebar */
.side-bar-bg {
width: 130px;
height: 100vh;
z-index: -1;
position: fixed;
background: #F7F7F7;
border: 1px solid #E0E0E0;
box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.50);
}
/* Wrapper around main content */
.content-container {
margin-top: 110px;
height:100%;
position:absolute;
width:100%;
}
/* Content elements*/
.lane,
.lane-head,
.phase,
.lane-content {
display: flex;
}
.lane {
margin-bottom: 1.25em;
//flex-direction: row;
align-items: center;
}
.lane-head {
min-width: 130px;
background-color: #ffffff;
box-shadow:0px 0px 0px 1px #BFC0C2 inset;
/* Flex & Layout */
flex-direction: column;
flex-wrap: wrap;
justify-content: center;
align-items: center;
align-self: stretch;
/**/
margin-right: 1em;
}
.lane-label {
font-weight: 500;
font-size: 13px;
color: rgba(82,94,106,0.65);
line-height: 22px;
margin-left: 1em;
margin-right: 1em;
text-align: center;
}
.lane-content {
z-index: -3;
}
/* Grid System */
.col-1 { min-width: 200px; max-width: 200px; }
.col-2 { min-width: 420px; max-width: 420px; }
.col-3 { min-width: 640px; max-width: 640px; }
.col-1, .col-2, .col-3 { margin-right: 20px; }
.textbox {
padding: 0.7em 1em 1.5em 1em;
color: #FFFFFF;
min-width: 200px;
max-width: 200px;
background-color: #78BE20;
}
.phase {
background: #005691;
align-self: stretch;
align-items: center;
padding: 0.6em 1em;
}
/* Typo */
.phase {
font-weight: 500;
font-size: 16px;
color: #FFFFFF;
}
.textbox h3 {
font-weight: bold;
font-size: 16px;
margin: 0 0 0.3em 0;
}
.textbox p {
font-weight: normal;
font-size: 13px;
margin: 0 0;
}
<header>
<h1>Header</h1>
</header>
<div class="side-bar-bg"></div>
<!------ CONTENT ------>
<div class="content-container">
<div class="lane">
<div class="lane-head"><span class="lane-label">Small Boxes</span></div>
<div class="lane-content">
<div class="phase col-2">Lorem Ipsum</div>
<div class="phase col-3">Bacon Ipsum</div>
<div class="phase col-2">Egg Ipsum</div>
</div>
</div>
<div class="lane">
<div class="lane-head"><span class="lane-label">Bigger Boxes</span></div>
<div class="lane-content">
<div class="textbox col-1">
<h3>Aenean commodo</h3>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</p>
</div>
<div class="textbox col-1">
<h3>Consequat</h3>
<p>Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus.</p>
</div>
<div class="textbox col-1">
<h3>Consequat</h3>
<p>Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus.</p>
</div>
<div class="textbox col-1">
<h3>Consequat</h3>
<p>Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus.</p>
</div>
<div class="textbox col-1">
<h3>Consequat</h3>
<p>Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus.</p>
</div>
<div class="textbox col-1">
<h3>Consequat</h3>
<p>Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus.</p>
</div>
<div class="textbox col-1">
<h3>Consequat</h3>
<p>Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus.</p>
</div>
</div>
</div>
</div>
The fixed left sidebar shall serve as a background to the "lane-headers".
The reason I want the lane-headers and the lane-content to be inside one div container is that later the whole canvas becomes dynamic and interactive. The content will be generated dynamically and the user will be able to interact with the canvas with drag-drop and so on.
I would appreciate your help very much, thanks in advance!
Hi you need to use javascript as well, once you scroll down or up add a class say posi_stat which will be position:static.and when you do horizontal scrolling just remove the class. In default case it will be position :fixed .
Something like this , you need to remove the class , and add on scrolldown too
$(function() {
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 500) {
//your code , what should be done//
}
});
});
Similarly to it for .scrollBottom(); .scrollRight(); .scrollLeft();
Okay I kind of found a solution to it thanks to this: Fixed position in only one direction in future releases of CSS?
Although the javascript solution did not work for me (I still can't figure out why), the CSS solution works pretty good.
By adding the following lines to the .lane-head class the problem was solved:
left: 0;
position: -webkit-sticky;
position: -moz-sticky;
position: -o-sticky;
position: -ms-sticky;
position: sticky;
Using the new "position: sticky" property you can perfectly stick any element basically anywhere you want.
Unfortunately Chrome still does not support this yet, but Safari and Firefox do.