Overlapping divs in flexbox column on smaller devices - html

I am trying to design a sidebar component for a mobile responsive web app. The goal is to have the sidebar respond to different screen sizes. However, as the screen size gets smaller, the bottom div will overlap the top div, which has a fixed height. You can see a generalized example of the issue here on codepen and described in this picture.
Here is a simplified snippet of the html/css from codepen
.container {
width: 10%;
height: 100%;
position: fixed;
display: flex;
flex-direction: column;
}
.div1 {
height: 250px;
position: absolute;
top: 0;
}
.div2 {
height: 75px;
position: absolute;
bottom: 0;
}
<div class='main'>
<div class='container'>
<div class='div1'>
content div1
</div>
<div class='div2'>
content div2
</div>
</div>
</div>
What properties do you have to give (div2) to stop overlapping when it begins to encroach on div1? The desired outcome is that div2 will always be aligned vertically and the overlap with continue passed the screens current height and you would just have to scroll down to see the content of div2.

Change the css properties of div2 to this:
.div2 {
max-height: 75px;
height: 20%;
position: absolute;
bottom: 0;
background-color: lightyellow;
border: 1px dotted black;
}
The maximum height of the div2 will be 75 (so on larger screens it will be 75px, as you intended), but, as you make the screen shorter, it will start to decrease.
You can also create a media query for smaller screens.

Here is one, replace the height measurement from px to % this will cause the divs to take height according to the height of their container the following is an example
.container {
width: 10%;
border: 1px solid black;
height: 100%;
position: fixed;
display: flex;
flex-direction: column;
}
.div1 {
height: 40%;
position: absolute;
top: 0;
background-color: lightblue;
border: 1px dotted black;
}
.div2 {
height: 25%;
position: absolute;
bottom: 0;
background-color: lightyellow;
border: 1px dotted black;
}
<div class='main'>
<div class='container'>
<div class='div1'>
content
</div>
<div class='div2'>
content
</div>
</div>
</div>

Related

Fixed sidebar leaves responsive wrapper

Why does my sidebar leave out of wrapper when its width reaches 1920px? I know I set the max-width on wrapper in order to maintain the size for 4k and bigger screens, but how do I keep the sidebar within the wrapper even when the size of the screen goes over 1920px?
html {
background-color: black;
}
.wrapper {
max-width: 1920px;
border: 2px dotted violet;
margin: 0 auto;
}
.sidebar {
width: 180px;
position: fixed;
top: 15%;
left: 0;
}
/*first section*/
.section {
margin-left: 150px;
border: 2px dotted yellow;
}
.publicarea {
width: 45%;
margin: 10rem auto;
border: 2px dotted blue;
}
.img-bookcontainer {
min-width: 10rem;
min-height: auto;
width: 55%;
height: 100%;
border: 2px dotted red;
margin: 0 auto;
}
.img-bookcontainer img {
max-width: 100%;
height: auto;
display: inline-block;
}
<div class="wrapper">
<div class="sidebar">
<div class="img-container">
<img src="/images/franzen-vertical-transparent.webp" alt="">
</div>
</div>
<div class="section">
<div class="publicarea">
<div class="img-bookcontainer">
<img src="/images/crossroads-3d-1.webp" alt="">
</div>
</div>
</div>
</div>
The reason why your sidebar is leaving the wrapper when the screen size reaches 1920px is because of the fixed position you set on the sidebar. When you set a fixed position, the element is taken out of the normal document flow and positioned relative to the viewport, which means it's not affected by the container's width or height.
To keep the sidebar within the wrapper, you can use absolute positioning instead of fixed positioning. This will position the sidebar relative to the wrapper instead of the viewport.
Here's what you can do:
Change the position property of the sidebar from "fixed" to "absolute":
.sidebar {
position: absolute;
top: 15%;
left: 0;
width: 180px;
}
Add "position: relative" to the wrapper so that the sidebar is positioned relative to the wrapper:
.wrapper {
max-width: 1920px;
border: 2px dotted violet;
margin: 0 auto;
position: relative;
}
With these changes, the sidebar will stay within the wrapper even when the screen size goes over 1920px.
I hope this helps! Let me know if you have any further questions.

How to make horizontal line span entire width of overflow: scroll element?

I have a "timeline" component and I want to put a horizontal line accross it:
.container {
width: 30vw;
height: 90vh;
background-color: aquamarine;
margin: 0 auto;
display: flex;
align-items: flex-start;
justify-content: center;
}
.timeline-box {
width: 90%;
margin-top: 50px;
}
.timeline-strip {
background-color: yellow;
height: 200px;
display: flex;
flex-direction: row;
overflow-x: scroll;
position: relative;
}
.timeline-strip:before {
content: '';
position: absolute;
top: 60%;
border-top: 2px solid black;
width: 100%;
height: 0px;
}
.point {
margin: 0 40px;
align-self:center;
}
.point:before {
content: '';
position: relative;
left: 50%;
border-left: 2px solid black;
top: 20px;
}
<div class="container">
<div class="timeline-box">
<div class="timeline-strip">
<div class="point">1</div>
<div class="point">2</div>
<div class="point">3</div>
<div class="point">4</div>
<div class="point">5</div>
<div class="point">6</div>
<div class="point">7</div>
<div class="point">8</div>
<div class="point">9</div>
<div class="point">10</div>
</div>
</div>
</div>
However, the horizontal line only has a width of the visible width - When I scroll the component the horizontal line stops.
If I set .timeline-strip to display: inline-flex, then the horizontal line goes all the way but now the timeline doesn't fit into the container. Thanks.
Move the overflow-x: scroll; to the timeline-box and make the timeline-strip display:inline-flex;
.container {
width: 30vw;
height: 90vh;
background-color: aquamarine;
margin: 0 auto;
display: flex;
align-items: flex-start;
justify-content: center;
}
.timeline-box {
width: 90%;
margin-top: 50px;
overflow-x: scroll;
}
.timeline-strip {
background-color: yellow;
height: 200px;
display: inline-flex;
flex-direction: row;
position: relative;
}
.timeline-strip:before {
content: '';
position: absolute;
top: 60%;
border-top: 2px solid black;
width: 100%;
height: 0px;
}
.point {
margin: 0 40px;
align-self:center;
}
.point:before {
content: '';
position: relative;
left: 50%;
border-left: 2px solid black;
top: 20px;
}
<div class="container">
<div class="timeline-box">
<div class="timeline-strip">
<div class="point">1</div>
<div class="point">2</div>
<div class="point">3</div>
<div class="point">4</div>
<div class="point">5</div>
<div class="point">6</div>
<div class="point">7</div>
<div class="point">8</div>
<div class="point">9</div>
<div class="point">10</div>
</div>
</div>
</div>
Explanation:
CSS layout is all about the interaction between container boxes and their content boxes.
So here, we have the timeline-strip::before content box which has width 100%. That's 100% the width of its container box generated by the timeline-strip box. When it's display:flex and no explicit width is set, its width follows the block-level layout rules and so is determined by its container box which is the timeline-box.
But the desired width for the timeline-strip box is the width of its contents. The contents are being laid out using flexbox rules, so there's only two choices for the display property: flex and inline-flex. Inline-flex has the desired behaviour, it's as wide as its contents. It can also be achieved with flex, by giving it a width:fit-content (and currently for Firefox, width:-moz-fit-content)
Now, because the timeline-strip box is as wide as its contents, and its container timeline-box box has a width limited by the window size, the timeline-strip box can be wider than its container box. The part of content that doesn't fit in its container box is called "overflow". It's the overflow setting on the container element that determines how that overflow is handled. In this case, the desired behaviour is to be able to scroll the content within the container box so to do that, the container timeline-box element is given the setting overflow-x: scroll; or overflow-x: auto;
You could set the position: fixed in .timeline-strip:before { and adjust top: 170px; and the width: 27vw.
I know this is a cluncy solution but this is what i would have done.
Changed CSS:
.timeline-strip:before {
content: '';
position: fixed;
top: 170px;
border-top: 2px solid black;
width: 27vw;
height: 0px;
}
Sorry but that's all I got. Maybe I was able to still help you out.

How to flex a div with position fix?

I am trying to get a page with 2 main elements, one side-panel that takes 20% of the viewport width and has the position fixed and the other would be the main window, taking 80% of the remaining space.
However it seems that giving the side panel a position: fix; top: 0 removes all of its flex properties.
Desired behavior: How can you manage to place a side panel in a proportional width of the screen and also have it keep its position fixed at top:0 ?
Note: It would be best if I could not use position: sticky
Here's a codepen to help. https://codepen.io/phil94/pen/vYORpMj
`
#side-panel {
bottom: 0px;
position: fixed ;
background: #acacac;
border: solid 3px;
width: 20%;
height: 100vh;
z-index: 1;
}
#container {
background: #3687d7;
display: flex;
}
#main {
background: #acacac;
border: solid 3px;
width: 80%;
height: 1200px;
}
<app>
<div id="container">
<div id="side-panel">
<ol>
<li>Tomatoe</li>
<li>Bananas</li>
<li>Pickles</li>
</ol>
</div>
<div id="main"></div>
</div>
</app>
Try this: position: sticky;
#side-panel {
bottom: 0px;
position: sticky;
top:0;
background: #acacac;
border: solid 3px;
width: 20%;
height: 100vh;
z-index: 1;
}

How to best layout a header with 4 divs next to each other and that should be mobile friendly?

I have the following layout for a header for a web page I am developing with the following configuration:
max-width: 1050px;
height: 150px;
What would be the best way to lay this out so that it is also as mobile friendly as possible.
My Idea was this: Each div has its width if its fixed width and also are display: inline-block. But then that is not so mobile friendly as I would have to add responsive blocks.
Has anyone a nicer idea I could do with that?
Here is what I have started with: https://jsfiddle.net/6ohe3hgp/
But not sure if its the right direction as it should also be mobile and by mobile i would probably stack the items on top of each other.
I can't think of a better way than using flexbox (which you also tagged the question with)
When all in a row, they will have the same height based on the one with most content, when stack vertically, on i.e. mobile's, they collapse to their content to make scrolling to a minimum.
Updated fiddle
.container {
max-width: 1050px;
margin: 0 auto; /* will center the container on wide screen */
display: flex;
}
.one {
width: 100px;
background-color: #f66;
}
.two {
width: 200px;
background-color: lightgreen;
}
.three {
flex: 1; /* this makes it take all the available space */
color: white;
background-color: black;
}
.four {
width: 200px;
background-color: lightblue;
}
#media screen and (max-width: 600px) {
.container {
display: block;
}
.container > div {
width: 100%;
}
}
<div>
<div class="container">
<div class="one">
Fixed width
</div>
<div class="two">
Fixed width, with several<br>
lines of text that will<br>
make all the other get<br>
equal height
</div>
<div class="three">
Dynamic width
</div>
<div class="four">
Fixed width
</div>
</div>
</div>
I using display table and table-cell to do this, see https://jsfiddle.net/8s07y8zg/
HTML
<div class="table">
<div class="td one">
One
</div>
<div class="td two">
Two
</div>
<div class="td three">
Three
</div>
<div class="td four">
Four
</div>
</div>
CSS
.table {
display: table;
table-layout: fixed;
width: 100%;
box-sizing: border-box;
color: #FFF;
}
.td {
display: table-cell;
height: 100px;
}
.one {
width: 150px;
background-color: red;
}
.two {
width: 200px;
background-color: green;
}
.three {
background-color: black;
}
.four {
width: 200px;
background-color: blue;
}
There's a variety of ways to do this. Some involve absolute position, some involve float, some involve display table-cell. Every technique have trade-offs (including mine below).
I noticed someone recommended bootstrap to solve this - I don't actually think it will, as this is not truly a "grid system", but a custom layout with a mix of dynamic and fixed width items.
I happen to prefer inline-block per your question, so would like to show you a couple of CSS tools that may or may not get you where you want. They leverage calc and vw
body, html {
margin: 0;
padding: 0;
}
div.container {
margin: 0;
padding: 0;
}
div.col {
box-sizing: border-box;
display: inline-block;
vertical-align: top;
/* the styles below are for illustration only */
min-height: 60px;
background: #ccc;
color: white;
padding: 10px 20px;
margin: 0;
}
div.col-1,
div.col-2 {
width: 150px;
background: #444;
}
div.col-4 {
width: 100px;
background: #aaa;
}
div.col-3 {
/* calculate value - 100vw (100% of viewport width) minus total width of other divs */
width: calc(100vw - 400px);
}
<div class="container">
<!-- NOTE: These divs are all on the same line to avoid
space between items. See https://css-tricks.com/fighting-the-space-between-inline-block-elements/ -->
<div class="col col-1">Fixed Width</div><div class="col col-2">Fixed Width</div><div class="col col-3">Variable Width</div><div class="col col-4">Fixed Width</div>
</div>
You can absolutely position all of them.
The trick is this: you can set the left:, width:, right: css parameters arbitrarily, and you can even neglect them.
So:
give the first div a left: 0 and a width: (in pixels).
to the second: left: (fix in pixels) and right (also fix in pixels).
to the third: left (fix, you can calculate it from the the widths of the first two) and right: (which is the width of the fourth)
And so on.
Absolute positioning works only inside display: block elements whose position: is different from static. So, you need this for the top div:
#topdiv {
display: block;
position: relative;
max-width: 1050px;
}
#div1 {
width: 150px;
left: 0;
display: block;
position: absolute;
}
#div2 {
display: block;
position: absolute;
left: 150px;
width: 150px;
}
#div3 {
display: block;
position: absolute;
left: 300px;
right: 150px;
}
#div4 {
display: block;
position: absolute;
right: 0;
width: 150px;
}
Note:

Content Divs below IMG with 100% width will not properly display below IMG

Issue: I am trying to make a layout with a fixed header for nag and below that will be an image that will fit the page. below that I want divs for content. the problem I am facing is that I cannot get both the image and the content divs to fit the screen and stack vertically.
The IMG is set to absolute because its the only way I could get it to 100% fit the screen without adjusting the margins. however when I do this the divs below that I am going to use for content: .body2 and .body3 do not show.
I want to get everything flush with the screen of the browser and stacked properly.
HTML:
<header>
<div id="headernav">
</div>
</header>
<div id="FixedBKG">
<img src="Images/imgbkg.JPG" id="bkgimg"/>
<div id="content">
<div class="body2">
</div>
</div>
<div id="content">
<div class="body3">
</div>
</div>
</div>
</body>
CSS:
#headernav {
height: 70px;
top: -10px;
left: 0px;
width: 100%;
background-color: black;
position: fixed;
z-index: 10;
color: white;
margin:0px auto;
}
#FixedBKG {
width: 100%;
height: 100%;
}
#bkgimg {
width: 100%;
left: 0px;
top: 0px;
position: absolute;
}
.body2 {
background-color: #C0C0C0;
height: 400px;
width: 100%;
left: 0px;
right: 0px;
display: block;
}
.body3 {
background-color: black;
height: 400px;
width: 100%;
left: 0px;
right: 0px;
display: block;
}
Ok, here's a second draft: FIDDLE.
General comments:
1.Try not to use positioning on a straight-forward layout like this one.
I changed the image to display: block and made it 100% of the div width - it will then adjust itself to the container, and you can
then adjust the container as you wish.
I changed the heights of the two lower divs and added a border so you could see them easier in the fiddle.
You really don't need the 100% widths, since divs are 100% by definition.
You might consider styling the body, and add a container element to give you more flexibility on formatting.
Let me know if you'd like to change anything else.
CSS
img {
display: block;
width: 100%;
}
#headernav {
height: 70px;
line-height: 70px;
text-align: center;
width: 100%;
background-color: black;
color: white;
}
#FixedBKG {
width: 100%;
}
.body2 {
background-color: #C0C0C0;
height: 200px;
width: 100%;
border: 1px solid red;
}
.body3 {
background-color: black;
height: 200px;
width: 100%;
border: 1px solid yellow;
}