I'm trying to lay out a web page that has three reasons - left, top right and bottom right. The left and bottom right regions should have scrollbars in them, and the entire page should fill the screen. I'm using Bootstrap 4.
I can get the scrollbars working properly around the left region. The problem is with the right regions - the horizontal scrollbar appears on the bottom-right region, as it should, but the vertical scrollbar appears on the entire page. Note that the bottom-right also has a vertical scroll bar, but it's disabled.
#outer {
height: 100vh;
overflow: none;
}
#left-col {
height: 100vh;
overflow: scroll;
background-color: #ff85d4;
}
#left-large {
height: 5000px;
width: 5000px;
}
#right-col {
height: 100vh;
}
#right-top {
background-color: #abff64;
}
#right-bottom {
overflow: scroll;
background-color: #ccddff;
}
#right-bottom-inner {
width: 2000px;
height: 2000px;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container-fluid">
<div class="row" id="outer">
<div class="col-9" id="left-col">
<div id="left-large">
Large left
</div>
</div>
<div class="col-3" id="right-col">
<div id="right-top">
<p>
Top 1
</p>
<p>
Top 2
</p>
<p>
Top 3
</p>
</div>
<div id="right-bottom">
<div id="right-bottom-inner">
Right bottom inner
</div>
</div>
</div>
</div>
</div>
How can I make the bottom-right region have its own scrollbars?
Like I said in the comments this is another way to do this with CSS grid which seems like the perfect tool for something this ... "gridy" :)
I gave all the boxes plenty of space you can scroll... adjust at will.
Update: I made the right-top box max-content and grow for as long as the content is while giving the right-bottom box a min height of 20px.
body {
padding: 0;
margin: 0;
}
.wrapper {
display: grid;
grid-template-columns: 1.6fr 0.4fr;
grid-template-rows: max-content minmax(20px, 1fr);
gap: 1rem;
height: 100vh;
width: 100vw;
}
.wrapper-inner {
height: 2000px;
width: 2000px;
}
.left,
.right-top,
.right-bottom {
overflow: auto;
padding: 1rem;
}
.left {
grid-row-start: 1;
grid-row-end: 3;
background: hotpink;
}
.right-top {
background: lime;
}
.right-bottom {
background: skyblue;
}
<div class="wrapper">
<div class="left">
<div class="wrapper-inner">
Large left
</div>
</div>
<div class="right-top">
<p>
Top 1
</p>
<p>
Top 2
</p>
<p>
Top 3
</p>
</div>
<div class="right-bottom">
<div class="wrapper-inner">
Right bottom inner
</div>
</div>
</div>
If you want to force a scrollbar on any block element, you'll need to set a fixed height and include an overflow-x:scroll or overflow-y:scroll property depending on where you want the scrollbar to appear.
If you want a horizontal scrollbar, use overflow-x:scroll;, if you want a vertical scrollbar, use overflow-y:scroll;
flex is magic
CSS
/*Allow children to auto fixed height*/
#right-col {
display: flex;
flex-direction: column;
}
#right-top {
height: fit-content; /*Only use essential*/
}
#right-bottom {
overflow: scroll; /*See child content*/
height:100%; /*use all remain height*/
}
Seeing that the height needs to be explicit (either as percentage or a fixed number), I couldn't find a CSS-only solution.
Instead I used a ResizeObserver to track changes to the size of the right-col and right-top elements (in my actual problem, the right-top element changes in size), calculated the right-bottom element (right-col.height - right-top.height basically), and applied it as a dynamic style on the right-bottom element.
Not pretty but it's working.
I tried using a CSS grid, too (instead of bootstrap altogether), but without explicitly specifying the height of the right bottom element, the scrollbars misbehaved there, as well.
Related
When creating my dashboard with flexbox css html, I have a scroll problem for example:
In the middle red container if I make it vertical the horizontal one does not work well for me opteniendo results like it expands the container descuadrando the design.
If I work the horizontal scroll does not work the vertical scroll expanding this.
I want it to work like this in the following image:
Desired result
I have tried many things with the flexbox like setting the height or width to 100% and even forcing the scroll, but I can't get the expected effect.
Your question is a bit broad, you should post your current solution next time to see which part is not working. For example, I couldn't really tell if the vertical scrollbar in the middle region is supposed to scroll the top or the middle part. Anyways, if you're set on using flexboxes, here's a way to do it:
body {
margin: 0;
}
main {
display: flex;
width: 100vw;
height: 100vh;
}
.left {
width: 20%;
background-color: cornflowerblue;
}
.left__header {
background-color: lightblue;
}
.middle {
display: flex;
flex-direction: column;
width: 40%;
background-color: salmon;
}
.middle__header {
flex-shrink: 0;
overflow-y: auto;
background-color: lightpink;
}
.middle__body {
overflow-x: auto;
}
.middle__footer {
margin-top: auto;
background-color: white;
}
.right {
width: 40%;
background-color: lightgreen;
}
<main>
<div class="left">
<div class="left__header">1</div>
<div class="left__body"></div>
</div>
<div class="middle">
<div class="middle__header">
<!-- Fixed width to simulate overflowing content -->
<div style="min-width: 2000px">1 2 3 4 5</div>
</div>
<div class="middle__body">
<!-- Fixed height to simulate overflowing content -->
<div style="min-height: 2000px">Content</div>
</div>
<div class="middle__footer">
Pia de Pagina
</div>
</div>
<div class="right">
SideBar Right
</div>
</main>
But if you don't plan on dynamically adding/removing elements or moving stuff around in the base layout (i.e. these regions stay the same during the use of the application) I'd recommend using CSS grid instead:
body {
margin: 0;
}
main {
display: grid;
grid-template:
"left-header middle-header right" min-content
"left-body middle-body right"
"left-body middle-footer right" min-content / 2fr 4fr 4fr;
width: 100vw;
height: 100vh;
}
.left__header {
grid-area: left-header;
background-color: lightblue;
}
.left__body {
grid-area: left-body;
background-color: cornflowerblue;
}
.middle__header {
grid-area: middle-header;
overflow-x: auto;
background-color: lightpink;
}
.middle__body {
grid-area: middle-body;
overflow-y: auto;
background-color: salmon;
}
.middle__footer {
grid-area: middle-footer;
background-color: white;
}
.right {
grid-area: right;
background-color: lightgreen;
}
<main>
<div class="left__header">1</div>
<div class="left__body"></div>
<div class="middle__header">
<!-- Fixed width to simulate overflowing content -->
<div style="min-width: 2000px">1 2 3 4 5</div>
</div>
<div class="middle__body">
<!-- Fixed height to simulate overflowing content -->
<div style="min-height: 2000px">Content</div>
</div>
<div class="middle__footer">
Pia de Pagina
</div>
<div class="right">
SideBar right
</div>
</main>
This results in the same output, but the HTML/CSS is much more readable IMO. It uses the grid-template property, which is fairly new, but should be available in most browsers.
I am trying to place 4 divs over a background image that would keep relative position and size as the browser is resized.
Here is the desired layout:
I have a big background (pink) that is placed with:
#screenFiller {
width: 100vw;
height: 100vh;
background-size: contain;
background-image: url("myimg.png");
background-repeat: no-repeat;
}
There are 4 main divs (red boxes). The two tops ones (side by side) contain a button each (blue boxes) with text (white squiggly lines) above the buttons but still in the red. I am positioning the divs next to each other using:
.flex {
display: flex;
justify-content: Left;
flex: none;
}
The main problem I am having is with the two top divs in that one is not keeping its height (it shrinks to content). I do understand that I will need to handle reducing the text size using a media query or something.
The stripped-down HTML looks like:
<div class="flex ">
<div class="boxme">
<div>
<p class="boldtext">Blha blah balh</p>
<div style="margin:10%;">
<button type="button" class="bigbut gborder5" onclick="window.location.href=''">Syart New</button>
</div>
</div>
</div>
<div class="boxme marl100">
<div>
<p class="boldtext">blah</p>
<div>
<button type="button" class="bigbut gborder5" onclick="window.location.href=''">Start New</button>
</div>
</div>
</div>
</div>
With boxme being:
.boxme {
background-color: white;
width: 25%;
height: 10%;
text-align: center;
}
Finally, all four divs are wrapped in a div with the following css
.relpos {
position: relative;
top: 36%;
left: 4%;
width: 85%
}
Please feel free to take me on an alternate path.
Bootstrap is available if that helps but currently, everything is just HTML and CSS.
Thank you in advanced for any consideration.
Normally, you never want to have fixed width, height, margin or paddings.
For your question, your flex values should be to put your content in the bottom left corner:
.container {
display: flex;
align-items: flex-end;
flex-direction: row; // default
}
Here is the full example that can be run as code snippet:
body {
height: 100vh;
}
body {
background-color: #fcf;
}
.container {
display: flex;
align-items: flex-end;
gap: 20px;
height: 100%;
padding: 20px;
}
.container>div {
background-color: #faa;
padding: 10px;
}
<div class="container">
<div>
<p>Text</p>
<button>Cick</button>
</div>
<div>
<p>Text</p>
<button>Cick</button>
</div>
</div>
I would strongly advise you to learn the fundamentals of html and css from other resources.
I am just facing a super weird problem. My actual goal was to build a scrollable flex-box content box between two sidebars (left and right) for an angular app. First I did a prototype in an html and it works fine! But then I started to implement it inside the app and the elements don't behave the same. In order to debug the problem, I replaced the elements and styles with exact the same tags and css styles, from my html-file, but it still doesn't look the same.
How it looks with the html-file
The sidebars have a full height
The centered content box has a vertical and horizontal scroll section.
This is the outcome of the angular app
The height of the sidebars don't stretch over the full height.
the centered box has ONLY a horizontal scroll section.
The padding of the container seems to have an effect of the .boxsidebar, because the .boxsidebar is not sticking on top (like in image 1).
Here is the code, which is used for both solutions. In the angular app, the html is added in the app.component.html and the style in app.style.scss:
<head>
<style>
body{
margin: 0;
}
.boxsidebar{
display: inline-block;
width: 25%;
height: 100%;
background-color: blue;
}
.container{
display: inline-block;
width: 74%;
}
.map{
display: inline-flex;
-webkit-flex-flow: column;
flex-flow: column;
height: 100%;
width: 74%;
box-sizing: border-box;
padding: 16px;
}
.toolbar{
width: 100%;
height: 100px;
background-color: chartreuse;
}
.sidebar{
display: inline-block;
width: 25%;
height: 100%;
background-color: blueviolet;
}
.wrapwrap{
min-height: 0;
flex: 1;
overflow: auto;
}
.someBigStuff{
background-color: aquamarine;
height: 2000px;
width: 2000px;
}
</style>
</head>
<div class="box">
<div class="boxsidebar">
<h3>Hello</h3>
<div class="sidebar_content">
</div>
</div>
<div class="container">
<div class="map">
<div class="toolbar">Hello</div>
<div class="wrapwrap">
<div class="someBigStuff"></div>
</div>
</div>
<div class="sidebar">
<h3>Hello</h3>
<div class="sidebar_content">
</div>
</div>
</div>
</div>
Final hint: I unchecked every additional style in the css-inspector window, so that both pages have the same base.
Thank you for your time and help!
I have 2 divs that are floated next to each other. In one of the divs I have an image that scales (both it´s height and width) when I decrease the size of the browser window. In the other div I have some other content, but this is only being scaled in width when I decrease the size of the browser window. I want both of the divs to have the same height at all times, even when they are being scaled. Is this possible?
If you want a live preview, please check out this link:
http://jjberg.com/cipher/index.html
I know part of the problem is that I´ve actually set a height of 500px to the cipherSide div. This is because so far I haven´t been able to make the height of this div closer to the height of the pinupSide div in any other way.
I tried to copy the declarations from the pinupSide and pinUpGirl to the cipherSide and verticalAlign divs, but to no avail. This only pushed the content in the cipherSide div all the way to the top.
<div class="container">
<div class="pinupSide">
<img class="pinUpGirl" src="images/pin_up_edited_x2.png" alt="Pin up girl">
</div>
<div class="cipherSide">
<div class="verticalAlign">
<h1> Dirty Diana </h1>
<p>Dirty Diana wants to send dirty love messages to her husband, but she does not want Big Brother to know about it. Try out the tool I made for her!</p>
<textarea rows="10" placeholder="Insert the text you want to cipher or decipher here!" required></textarea>
<button id="cipherIT">Cipher It!</button>
<button id="deCipher">Decipher!</button>
<p id="newOne"></p>
</div><!-- verticalAlign -->
</div><!-- cipherSide -->
</div><!-- container -->
.container {
max-width: 992px;
height: 100%;
margin: 0 auto;
background: blue;
}
.pinupSide {
background: green;
width: 50%;
height: 100%;
float: left;
}
.pinUpGirl {
max-width: 100%;
max-height: 100%;
background: black;
}
.cipherSide {
position: relative;
background: red;
width: 50%;
height: 500px;
float: left;
}
.verticalAlign {
position: absolute;
top: 25%;
height: 50%;
width: 100%;
background: yellow;
}
I want both of the divs to have the same height at all times, no matter how I´m scaling the width of the browser window.
Considering you code I assume you want the two elements to have the same height but also the same width at all time. I also assume you want the image to be as big as possible inside the left element without being distorted. Is that right?
If you can use CSS Grid, you can achieve that layout with a grid made up of two columns of each 1fr, which represent one fraction of the available space. See the following code:
The <img> element has its width set to 100% so that it is as big as possible inside its parent element, and its parent element has the font-size set to 0 to remove an unwanted space below the image.
body {
margin: 0;
background-color: #3ff4fe;
}
.container {
max-width: 992px;
margin: auto;
display: grid;
grid-template-columns: 1fr 1fr;
}
.image {
background-color: black;
font-size: 0;
}
.image img {
width: 100%;
}
.text {
background-color: red;
}
<div class="container">
<div class="image">
<img src="http://jjberg.com/cipher/images/pin_up_edited_x2.png" alt="Pin up girl">
</div>
<div class="text">
Some text
</div>
</div>
Does this help?
I second the use of grid like Auguste said. You could also use flex-box instead of floats and absolute positioning. Here is one possible implementation.
You'll probably have to play with object-fit on the image. Or just set the background of the pinup side to be the image and change the positioning through background properties. Either way it should work out.
You can also set hard heights and widths if you want to and just you the flex-box for positioning.
If you run the code snippet be sure to view it full screen because it uses view-port units for the height of the container.
* {
box-sizing: border-box;
}
.container {
padding: 2rem;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.pinupSide,
.cipherSide {
flex: 1 1;
height: 100%;
display: flex;
justify-content: center;
flex-direction: column;
}
.pinupSide {
align-items: center;
background: rgba(0,0,0,.6);
}
.pinUpGirl {
width: 100%;
object-fit: cover;
object-position: 50% 50%;
}
.cipherSide {
align-items: flex-start;
background: rgba(231, 76, 60, 1)
}
.heading-group {
background: rgba(241, 196, 15, 1);
}
textarea {
width: 100%;
}
.button-group {
width: 100%;
}
<div class="container">
<div class="pinupSide">
<img class="pinUpGirl" src="https://images.unsplash.com/photo-1530650819615-f14c8a735dd8?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1055&q=80" alt="Pin up girl">
</div>
<div class="cipherSide">
<div class="heading-group">
<h1> Dirty Diana </h1>
<p>Dirty Diana wants to send dirty love messages to her husband, but she does not want Big Brother to know about it. Try out the tool I made for her!</p>
</div>
<textarea rows="10" placeholder="Insert the text you want to cipher or decipher here!" required></textarea>
<div class="button-group">
<button id="cipherIT">Cipher It!</button>
<button id="deCipher">Decipher!</button>
</div>
<p id="newOne"></p>
</div><!-- cipherSide -->
</div><!-- container -->
EDIT: My example was to complicated. So I made a simpler one.
http://codepen.io/knobo/pen/gaZVoN
.top grows beyond the available size of the html element. I don't want any content outside the current viewport which is 100vh, but I don't know the height of .bottom which can vary.
This line:
max-height: calc(100vh - 60px);
Makes it look like this works. But it does not, because I don't know the height of .bottom, which I just estimated to 60px;
<div class="page">
<div class="top">
<div class="left">Some text</div>
<div class="right">
<img src="http://placehold.it/350x1800">
</div>
</div>
<div class="bottom">
<button>Click</button>
<button>Click</button>
<button>Could be several lines</button>
</div>
</div>
html, body {
max-height: 100vh;
}
Css
.page {
display: flex;
flex-direction: column;
height: 100%;
}
.top {
flex: 1 1 auto;
display: flex;
overflow: hidden;
max-height: calc(100vh - 60px);
/*
I don't know the height of .bottom
It can change when browser is resized too..
How do I solve this.
*/
}
.left {
flex: 1 1 auto;
}
.bottom {
padding: 10px;
flex: 1 1 auto;
background-color: teal;
}
EDIT2: (included the original links from the first version)
http://codepen.io/knobo/pen/epboBv (css version. Does not work)
http://codepen.io/knobo/pen/wKRNjr/ (js version. Works. But I want to know how to do it with css.)
EDIT3
Screenshots:
When browser window is small, the bottom row disappears, when div.right is too big.
When browser window is large everything shows up (corectly)
This is how it should be: div.top is scaled down, and bottom row is stil visible. I was able to do it with javascript. I guess it should be possible with css too.
The solution is surprisingly easy.
.right {
position: relative;
/* width: Do something with width here. */
}
.nooverflow {
position: absolute;
}
then wrap the content of .right with class="nooverflow"
<div class="right">
<div class="overflow">
{{ Content of .right }}
</div>
</div>