Fixed column when vertically scrolling. Unfixed when horizontally scrolling. Pure CSS - html

I have a centered page with two columns filling the window height. The left column is fixed, so it is always visible when scrolling. The right column wraps the page content and will be usually larger than the left column.
HTML:
<div class="main-container">
<div class="col1">
<p>Fixed column</p>
</div>
<div class="col2">
<p>Content column</p>
</div>
</div>
CSS:
.main-container {
width: 300px;
height: 100%;
margin: 0 auto;
}
.col1 {
position: fixed;
width: 100px;
height: 100%;
background: fuchsia;
}
.col2 {
width: 200px;
margin-left: 100px;
background: cyan;
}
When the browser window is narrower than the page width (300px in this example), a horizontal scrollbar will appear, and the fixed column will keep fixed and fly over the content column. I want to avoid this.
Can I achieve this vertical-only fixing with pure CSS (no Javascript)?
See the full example Plunker.
Clarification: the vertical scrollbar must be the window scrollbar, not an inner scrollbar in .col2.

I think that in your case you need to use media queries or twitter bootstrap

Demo
css
.col1 {
position: fixed;
width: 100px;
height: 100%;
background: fuchsia;
z-index: 1; /* z-index lower than than .col2 */
}
.col2 {
position: relative; /* position needed for z-index to work */
width: 200px;
margin-left: 100px;
background: cyan;
z-index: 2; /* z-index higher than than .col1 */
}

Just add the CSS property z-index:-1; to the fixed column .col1, It will do the trick

You could work with absolute positioning and overflow on the .col2 container only. This way you still have your fixed column on vertical scroll but not on horizontal scroll.
jsFiddle: http://jsfiddle.net/85fyC/
CSS:
html, body {
height: 100%;
overflow-y: hidden;
}
.main-container {
position: relative;
width: 300px;
height: 100%;
margin: 0 auto;
}
.col1 {
position: absolute;
width: 100px;
height: 100%;
background: fuchsia;
}
.col2 {
width: 200px;
height: 100%;
margin-left: 100px;
overflow: auto;
}
.col2 .inner {
background: cyan;
}
.col2 .inner p {
margin: 0;
}

Related

How to get a div to scroll vertically and reveal gradient

I'm trying to get three divs side-by-side horizontally. I want the left-most div to scroll, so the gradient reveals itself as the user scrolls. For some reason the divs aren't adjacent and the left one isn't scrolling, and I don't know why.
* {margin: 0; padding: 0; box-sizing: border-box}
html, body {width: 100%; height: 100%}
.overall {
height: 100%;
}
.scroll {
width: 10%;
height: 200%;
background: linear-gradient(#e66465, #9198e5);
overflow-y: scroll;
}
.one {
width: 70%;
height: 100%;
background: lightgreen;
}
.two {
width: 20%;
height: 100%;
background: lightblue;
}
<div class="overall">
<div class="scroll"></div>
<div class="one"></div>
<div class="two"></div>
</div>
They are not placed horizontally because div's are block-level elements by default, meaning they occupy the entire row / width of the screen.
Nowadays typically, if one needs to place them horizontally, he/she does it with the Flexbox or display: flex set on the parent element. Of course there are also other ways of doing it.
And for the scrolling, it doesn't scroll because there's nothing to scroll. Put some "tall" enough content (which is greater than the set height of 200%) inside the .scroll div and see it in "action":
* {margin: 0; padding: 0; box-sizing: border-box}
html, body {width: 100%; height: 100%}
.overall {
display: flex; /* displays flex-items (children) inline by default */
height: 100%;
}
.scroll {
/*width: 10%;*/
flex: 1; /* flexbox way of defining width */
height: 200%; /* necessary ? */
background: linear-gradient(#e66465, #9198e5);
overflow-y: auto; /* modified, only shows the scrollbar when needed */
}
.one {
/*width: 70%;*/
flex: 7;
/*height: 100%; not necessary, takes the parents height */
background: lightgreen;
}
.two {
/*width: 20%;*/
flex: 2;
/*height: 100%;*/
background: lightblue;
}
<div class="overall">
<div class="scroll">
<p style="height: 250%">Some looooong paragraph which is taller that its parent...just for demo...</p>
</div>
<div class="one"></div>
<div class="two"></div>
</div>

How to make two large divs stay side by side, and take up same width at all screen widths [duplicate]

This question already has answers here:
Two divs, one fixed width, the other, the rest
(10 answers)
Closed 4 years ago.
So I am making a website that uses this setup. A nav, a panel, and a main content area. The content area is filled with divs that will be resized by media queries. The issue is I want the panel to be a fixed width, and the main area to take up the rest of the screen on all screen sizes and automatically downsize. Example. If the panel's 255px width is 25% of the screen, I want the width of main to be the next 75% of the screen. It either takes up too much space and makes it scroll horizontally, or goes down to the new line. What would be the best solution
.panel {
width: 255px;
height: 100%;
position: relative;
float: left;
background-color: orange;
}
.main {
width: 88%;
height: 100%;
position: relative;
float: left;
background-color: red;
}
.nav {
width: 100%;
height: 300px;
background-color: yellow;
}
<div class="panel">
T
</div>
<div class="main">
<div class="nav">
T
</div>
T
</div>
LINK- https://jsfiddle.net/cn6q6keu/2/
You can do it with float and flex.
Here is a float solution:
*{
margin: 0;
border: 0;
padding: 0;
box-sizing: border-box;
}
html, body{
height: 100%;
min-height: 100%;
}
.clear-fix:before, .clear-fix:after{
display: block;
content: '';
clear: both;
}
#main{
height: 100%;
}
.panel, .nav{
float: left;
padding: 15px;
height: 100%;
min-height: 100%;
overflow: auto;
}
.panel{
background: pink;
width: 225px;
}
.nav{
background: red;
width: calc(100% - 225px);
}
<div id="main" class="clear-fix">
<div class="panel"></div>
<div class="nav"></div>
</div>
Fiddle link: https://jsfiddle.net/3rxdub8d/5/
Here is a flex solution:
*{
margin: 0;
border: 0;
padding: 0;
box-sizing: border-box;
}
html, body{
height: 100%;
min-height: 100%;
}
#main{
display: flex;
height: 100%;
}
.panel, .nav{
padding: 15px;
height: 100%;
min-height: 100%;
overflow: auto;
}
.panel{
background: pink;
width: 225px;
}
.nav{
background: red;
flex: 1;
}
<div id="main" class="clear-fix">
<div class="panel"></div>
<div class="nav"></div>
</div>
Fiddle link: https://jsfiddle.net/xxwsa4oh/2/
I'm afraid you're gonna have to apply this rule to the fixed width, so you'll be able to convert it to a relative unit like %:
(target รท context) * 100 = result
Target = panel fixed width;
Context = parent element width;
Result = Converted fixed width value in percentage.

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:

CSS Position Fixed Maintain Height

I have a div with content and an outter div that's just a wrapper. I'm trying to combine the css from the outter div to the inner div so i can remove the outter div. When I do that, the div is no longer visible(assuming because of zero height). I thought maybe it was the order so I tried rearranging the css but still no luck.
#div1 {
min-height: 200px;
width: 100vw;
}
#div2 {
/* min-height: 200px;
width: 100vw; */
position: fixed;
height: 100%;
width: 100%;
background-color: #74CFAE;
font-size: 25px;
line-height: 40px;
z-index: -1;
}
#div3 {
position: relative;
height: 600px;
width: 100vw;
background-color: #333;
}
<div id="div1">
<div id="div2">
<p> I want the following div to scroll over this content.</p>
</div>
</div>
<div id="div3"></div>
If you comment out the css for 'div1' and combine it with 'div2' you will see what I am talking about.
Is this a case that requires a wrapper? or is there something inherently wrong with my css?
My take on it: if you know height of div2, you can drop div1, but you'll have to place div3 at a definite top.
If you don't know div1/2 height and don't want to reposition dynamically div3, it seems like div1 as a wrapper is a good solution.
A suggestion with known div2 height:
#div2 {
height: 100px
width: 100vw;
position: fixed;
background-color: #74CFAE;
font-size: 25px;
line-height: 40px;
z-index: -1;
}
#div3 {
position: relative;
height: 600px;
width: 100vw;
background-color: #333;
top: 100px;
}
https://jsfiddle.net/oahurc53/1/

Scrollable div inside container without known height

I'm trying to scroll items within a container without known height. I have div itemsHolder which fills up the rest of wrapper container. wrapper container can have any height but contains header container which has fixed height. So I don't know the height of itemsHolder and I need div items to be scrollable. Here's the code I tried but was unsuccessful.
To sum up. There's wrapper container containing header and itemsHolder. wrapper has variable height, header has fixed height and itemsHolder fills the rest of wrapper (wrapper.height - header.height = itemsHolder.height). I need div items to be scrollable within itemsHolder without using JS.
Thanks.
<div class="wrapper">
<div class="header">
title
</div>
<div class="itemsHolder">
<div class="items">
<div class="item">text</div>
<div class="item">text</div>
<div class="item">text</div>
</div>
</div>
</div>
CSS:
.wrapper {
background: #ccc;
height: 200px;
width: 100px;
overflow: hidden;
}
.header {
height: 50px;
background: #00ffff;
}
.items {
background: #ff00ff;
}
.itemsHolder {
overflow: scroll;
}
.item {
width: 100px;
height: 80px;
float: left;
}
http://jsfiddle.net/B2XUL/
Update: I don't know the size of wrapper, it may be different each time and therefore I don't know the height of itemsHolder so I can't set it fixed.
Do the following:
.wrapper {
background: #ccc;
height: 200px;
width: 100px;
}
.itemsHolder {
height: 100%;
overflow: auto;
overflow-x:hidden;
background: #ccc;
}
Demo
Set the height of itemsHolder and it will add the scroll if necessary
.itemsHolder {
overflow: scroll;
height: 150px;
}
http://jsfiddle.net/B2XUL/4/
EDIT: I'm very sorry I can't provide an explanation as to why, but adding bottom padding to .wrapper and setting the height of .itemsHolder seems to work. You may have to reduce size of wrapper by 35px when it is set.
Any explanation for this or even a better fix would be welcomed.
.wrapper {
background: #ccc;
height: 200px;
width: 100px;
overflow: hidden;
padding-bottom: 35px;
}
.itemsHolder {
overflow: scroll;
height: 100%;
}
(also .items seems redundant?)
see updated fiddle
Using calc() CSS property, you can achieve wrapper.height - header.height = itemsHolder.height
.itemsHolder {
overflow: auto;
height:calc(100% - 50px);
}
Add overflow auto:
.wrapper {
background: #ccc;
height: 200px;
width: 100px;
overflow: hidden;
}
.header {
height: 20%;
background: #00ffff;
}
.items {
background: #ff00ff;
}
.itemsHolder {
height: 80%;
overflow: auto;
overflow-x: hidden;
}
.item {
width: 100px;
height: 80px;
float: left;
}
Add overflow-x: hidden if you only want vertical scroll.
Updated Fiddle
js fiddle demo
.wrapper {
background: #ccc;
height: 200px;
width: 100px;
overflow: hidden;
}
.header {
height: 50px;
background: #00ffff;
}
.items {
background: #ff00ff;
}
.itemsHolder {
max-height: 150px;
overflow-y: scroll;
overflow-x: hidden;
}
.item {
width: 100px;
height: 80px;
float: left;
}