Creating a cross-browser fixed height scrollable display: table-row - html

I am trying to create a container, of height 80% of the page height, which has a fixed height header and footer with a content pane that stretches to fit the rest of the available space.
I've tried to use display: table with the following layout:
<body>
<div class="ticket">
<div class="header">header</div>
<div class="body">
<div class="wrapper">
<div class="content">content</div>
</div>
</div>
<div class="footer">footer</div>
</div>
</body>
With these styles
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
.ticket {
background: #ccc;
width: 600px;
margin: 0 auto;
height: 80%;
display: table;
}
.header {
background: blue;
height: 36px;
display: table-row;
}
.body {
background: orange;
display: table-row;
}
.wrapper {
height: 100%;
overflow-y: auto;
overflow-x: hidden;
}
.content {
height: 600px;
}
.footer {
background: green;
height: 72px;
display: table-row;
}
In Chrome this gives me a scrollable middle panel that grows with the height of the container:
Unfortunately this doesn't work in IE8 or Firefox, the '.body' div stretches to fit the '.content'.
Is there a way to do this that will work cross browser, and IE8+?

Check out http://caniuse.com/#search=flexbox and/or http://caniuse.com/#search=vh
Those are the ways to get it, but none of them works on IE 8.
You must use JS

Related

Contenteditable div resizing instead adding scrollbar

I'm having problem with my div with contenteditable=true which break my whole page.
When you type a lot of text, instead adding scrollbar it make div bigger so it move others parts of the page...
So what I would like my editable div fill remaining width and height of the page but add scrollbar when text being too big whitout moving others elments of the page. Thanks
JsFiddle
HTML
<body>
<h1>TEXT</h1>
<div class="all">
<div class="container">
<div class="lines"></div>
<div class="editor" contenteditable="true" spellcheck="false"></div>
</div>
<div class="manage">
<h1>TEXT</h1>
</div>
</div>
</body>
CSS
html, body {
margin: 0;
padding: 0;
display: flex;
height: 100%;
width: 100%
}
h1 {
margin: 20px;
}
.all {
display:flex;
flex-direction: column;
width: 100%;
height: 100%;
}
.container {
display: flex;
width: 100%;
height: 400px;
overflow: auto;
}
.lines {
background-color: red;
border-radius: 20px 0 0 20px;
height: 100%;
width:40px;
}
.editor {
border-radius: 0 20px 20px 0;
background-color: orange;
width: 100%;
height: 100%;
}
All you need to do is to add a max-width property to your .editor class.
Here is a working code: https://codesandbox.io/s/html-code-editor-forked-g27d9o?file=/index.html

Fixed position sidebar within a flex container

I have a layout which uses flexbox to position a main content section and a sidebar element beside each other, with justify-content: space-between for consistent spacing within a container, however I need the sidebar on the right to also scroll down the page with the user by using position: fixed, whilst also remaining pinned to the right edge of the container.
Example pen: https://codepen.io/StyleMeLikeOneOfYourFrenchGirls/pen/BazQOLj
.container {
width: 1000px;
margin: auto;
border: 1px solid black;
}
.content {
display: flex;
justify-content: space-between;
}
.left-content {
height: 1000px;
width: 70%;
background-color: red;
}
.right-sidebar {
height: 200px;
width: 20%;
background-color: yellow;
/*position: fixed;*/
}
<div class="container">
<div class="content">
<div class="left-content">
left content
</div>
<div class="right-sidebar">
right sidebar
</div>
</div>
</div>
I understand that fixed removes the element from document flow, and thus eliminates the simplicity of the flex layout and the ability to 'contain' something within it's parent element.
I've been able to achieve something close to what I want, but it requires specific values for different viewport widths (e.g. using Bootstrap's offset classes, transform: translateX() or various combinations of margins). These methods are messy though, and don't provide a consistent solution to keeping the sidebar aligned with the edge of the parent container.
Is there a simpler/more elegant solution to this problem?
You can use position: sticky;. It respects the flex and has a fixed purpose.
DEMO:
.container {
width: 1000px;
margin: auto;
border: 1px solid black;
}
.content {
display: flex;
justify-content: space-between;
}
.left-content {
height: 1000px;
width: 70%;
background-color: red;
}
.right-sidebar {
height: 200px;
width: 20%;
background-color: yellow;
position: -webkit-sticky;
position: sticky;
top: 0;
}
<div class="container">
<div class="content">
<div class="left-content">
left content
</div>
<div class="right-sidebar">
right sidebar
</div>
</div>
</div>
Please have a look...
body {
margin: 0;
}
.container {
width: 1000px;
display: block;
margin: 0 auto;
}
.content {
background: #999;
height: 100vh;
overflow: auto;
display: flex;
}
.leftContent {
display: flex;
width: calc( 100% - 300px );
}
.rightSidebar {
position: absolute;
right: calc(50% - 500px);
background: #666;
height: 100vh;
width: 300px;
overflow: auto;
}
<div class="container">
<div class="content">
<div class="leftContent">
a a a a a a a a a a a a a a a a a. a a a a. a a a a a a a a. a a a a a a a aa. a a a a a a a a a a a a a a a a a a a. a a a a. a a a a a a a a. a a a a a a a aa. a aa<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>
</div>
<div class="rightSidebar">
b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>
</div>
</div>
</div>
Here is a try with minimum impact on your code.
The setup you have limits a bit the options you have, but I think below Pen would be a nice workaround.
.left-content {
height: 1000px;
width: 100%;
max-width: 70%;
background-color: red;
}
.right-sidebar {
height: 200px;
width: 100%;
max-width: 15%;
background-color: yellow;
position: fixed;
right: 20%;
}
CodePen
Sidebar on the right hand side scrolls down the page with the user by using position: fixed, whilst also remaining pinned to the right edge of the container.

Extending height of a div within another div

I'm having a problem with two wrappers that I am using. I want to make the #wrapper always extend to the bottom of the screen. This is now working by using min-height: 100%;. Within this div I'm using another wrapper, #page-wrapper, which should be extended to the bottom of the #wrapper div. To make this work, the #wrapper div has to be set to height: 100% instead of min-height. Is there a way to achieve both?
#wrapper {
width: 100%;
background-color: #2f4050;
min-height: 100%;
position: relative;
}
#page-wrapper {
padding: 0 15px;
min-height: 100%;
background-color: white;
height: 100%;
}
<div id="wrapper">
<div id="page-wrapper"></div>
</div>
Try using viewport units.
#page-wrapper {
min-height: 100vh;
}
Example 1:
body {
margin: 0;
}
#wrapper {
background: pink;
}
#page-wrapper {
min-height: 100vh;
background: gold;
}
<div id="wrapper">
<div id="page-wrapper">
</div>
</div>
Example 2:
body {
margin: 0;
}
#wrapper {
background: pink;
}
#page-wrapper {
min-height: 100vh;
background: gold;
}
<div id="wrapper">
<div id="page-wrapper">
<div style="height:200vh;"></div>
</div>
</div>

Scroll list of columns vertically with fixed header but scroll list and header horizontally

jsfiddle: https://jsfiddle.net/jefftg/1chmyppm/
The orange header columns and the white list rows scroll together horizontally, which is desired. However, I want the white list rows to scroll vertically with the orange header fixed at the top. They currently don't. I'm looking for this to work in modern browsers with HTML5/CSS3.
css
.container {
width: 800px;
height: 600px;
overflow-x: auto;
overflow-y: hidden;
}
.header-container {
display: flex;
}
.header-cell {
height: 40px;
min-width: 500px;
background-color: orange;
border: 1px solid red;
}
.data-container {
overflow-y: auto;
overflow-x: hidden;
display: inline-block;
}
.data-row {
overflow-x: hidden;
display: flex;
}
.data-row-cell {
height: 30px;
min-width: 500px;
background-color: white;
border: 1px solid black;
}
html
<div class="header-container">
<div class="header-cell">A</div>
<div class="header-cell">B</div>
<div class="header-cell">C</div>
<div class="header-cell">D</div>
</div>
<div class="data-container">
<div class="data-row">
<div class="data-row-cell">
A1
</div>
<div class="data-row-cell">
B1
</div>
<div class="data-row-cell">
C1
</div>
<div class="data-row-cell">
D1
</div>
</div>
......
</div>
This can be done with pure CSS and you don't need JavaScript.
I've modified your JSFiddle to work the way you are requesting: https://jsfiddle.net/48386nvn/3/
Essentially, .header-container needs to be positioned absolute relative to the .container element:
.container {
width: 800px;
height: 600px;
overflow-x: auto;
overflow-y: hidden;
/* added this: */
position: relative;
}
.header-container {
display: flex;
/* added these: */
position: absolute;
top: 0;
left: 0;
}
The above-mentioned CSS will stick the orange header where you want it and maintain the width you need it to be.
Next, you'll need to make the data scrollable, which is done by doing the following calculation:
height: heightOfParentContainer - heightOfHeaderRow;
The header cell height is 40px (42px when respecting the borders) It also needs a margin-top equal to the height of the header row:
.data-container {
overflow-y: auto;
overflow-x: hidden;
display: inline-block;
/* added these: */
margin-top: 40px;
height: 560px;
}
This should make sure that the header row is not overlapping the data container, and that the height of the data takes up the rest of the space of the overall container.
I was able to get the desired result by simply adding height: 558px to .data-container: jsfiddle.net/jefftg/1chmyppm/2
You don't need to add the overflow to every element, just the elements that need scrolling,
all I did is gave your .data-containera display:block and a certain height so that the overflow-y:auto can work, you can change the height with what you see fits in your page.
this here shows my solution, I hope it helps.
$(".header-container").scroll(function() {
var scrollPercentage = 100 * this.scrollLeft / (this.scrollWidth - this.clientWidth);
$(".data-container").scrollTop(scrollPercentage);
});
.container {
width: 800px;
height: 600px;
}
.header-container {
display: flex;
overflow-x: auto;
}
.header-cell {
height: 40px;
min-width: 500px;
background-color: orange;
border: 1px solid red;
}
.data-container {
overflow-y: auto;
overflow-x: hidden;
display: block;
height: 100px;
}
.data-row {
display: block;
}
.data-row-cell {
height: 50px;
min-width: 500px;
background-color: white;
display: block;
border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="header-container">
<div class="header-cell">A</div>
<div class="header-cell">B</div>
<div class="header-cell">C</div>
<div class="header-cell">D</div>
</div>
<div class="data-container">
<div class="data-row">
<div class="data-row-cell">
A1
</div>
<div class="data-row-cell">
B1
</div>
<div class="data-row-cell">
C1
</div>
<div class="data-row-cell">
D1
</div>
</div>
......
</div>

Horizontally centering two stacked divs, when one has a vertical scrollbar

Centering elements horizontally is easy using margin: 0 auto;
However, it doesn't work if there are two elements stacked in a column and one has a scrollbar and the other does not. In that case, the two horizontal centered elements aren't aligned anymore.
Question: Is there any way to align the two elements without using Javascript to adjust the margin of the first one?
JSFIDDLE DEMO
<head>
<style>
body {
margin: 0; height: 100vh;
}
.header {
height: 50px; background: red;
}
.content {
overflow-y: scroll; background: blue;
}
.inner {
background: rgba(255,255,255,.5); max-width: 300px;
margin: 0 auto; min-height: 50px;
}
.content > .inner {
min-height: 300px;
}
</style>
</head>
<body>
<div class="header">
<div class="inner"></div>
</div>
<div class="content">
<div class="inner"></div>
</div>
</body>
The main problem is obviously the centering. So why not circumvent it and use margin-left?
Try this CSS:
.inner { margin-left: calc(50vw - 150px); } /* half viewport width less half element width
(for precise centering) */
body {
margin: 0;
height: 100vh;
}
.header {
height: 50px;
background: red;
}
.content {
background: blue;
overflow-y: scroll;
}
.inner {
background: rgba(255,255,255,.5);
max-width: 300px;
/* margin: 0 auto; <-- remove */
margin-left: calc(50vw - 150px); /* new */
min-height: 50px;
}
.content > .inner {
min-height: 300px;
}
<div class="header">
<div class="inner"></div>
</div>
<div class="content">
<div class="inner"></div>
</div>
Revised Fiddle
Answer from Wes in chat:
This can be solved by adding a scrollbar to the first one, but hiding it from the user.
.header {
height: 50px;
background: red;
overflow-y: scroll;
width: 120%;
margin-left: -10%;
}
JSFIDDLE DEMO
If you're concerned a user could have a scrollbar wider than 10%, increase it width: 300% and margin-left: -100%. If somebody has a scrollbar as wide as the page, he / she can't use the page anyway.