Fixed div get width from parent in 100% - html

I have tried to assign a 100% of the parent to a fixed div but is taking the 100% of the screen.
I prepared the code here
http://codepen.io/rodboc/pen/ZOOEWp
HTML
<div id="wrapper">
<div class="box">
<div class="header">
<p>Header</p>
</div>
<div class="content">
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
</div>
</div>
</div>
CSS
#wrapper {
width: calc(100% / 3);
height: 900px;
background: #ecf0f1;
margin: 0 auto;
padding: 10px;
}
#wrapper .box {
width: 100%;
}
#wrapper .header {
width: inherit;
position: fixed;
background: #2ecc71;
}
#wrapper .content {
width: inherit;
background: #27ae60;
}
if a define the width for the parent in px works, but I can't do that, should be in 100%

It's pretty simple actually, move the header outside the box div.
body, html {
margin: 0;
width: 100%
}
#wrapper {
width: calc(100% / 3);
height: 900px;
background: #ecf0f1;
margin: 0 auto;
padding: 10px;
}
#wrapper .box {
background: lime;
}
#wrapper .header {
width: inherit;
position: fixed;
background: #2ecc71;
}
#wrapper .content {
background: #27ae60;
}
<div id="wrapper">
<div class="header">
<p>Header</p>
</div>
<div class="box">
<div class="content">
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
</div>
</div>
</div>

body, html {
width: 100%
}
#wrapper {
width: calc(100% / 3);
height: 900px;
background: #ecf0f1;
margin: 0 auto;
}
#wrapper .box {
width: 100%;
max-width: 238px;
margin: 10px;
background: lime;
}
#wrapper .header {
width: 100%;
position: fixed;
background: #2ecc71;
max-width: inherit;
}
#wrapper .content {
width: 100%;
background: #27ae60;
}
<div id="wrapper">
<div class="box">
<div class="header">
<p>Header</p>
</div>
<div class="content">
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
<p>Content here Lorem Ipsum</p>
</div>
</div>
</div>
Fixed position elements is not relative with its parent anymore.
Based on the documentation :
position:fixed MDN
Fixed Do not leave space for the element. Instead, position it at a
specified position relative to the screen's viewport and don't move it
when scrolled. When printing, position it at that fixed position on
every page. This value always create a new stacking context.
One way to fix this is to the max-width of parent and let the child inherit it.
So in your case it should be the same on the snippet i attached.

This might solve your issue, change the styling of the header class like this:
#wrapper .header {
width: 100%;
position: fixed;
background: #2ecc71;
max-width:calc(100% / 3);
}
Check out if it could do for you:
http://output.jsbin.com/jaxasikose/

Okay here is how you fix it with a clean code:
#wrapper {
width: calc(100% / 3);
height: 900px;
background: #ecf0f1;
margin: 0 auto;
padding: 10px;
}
#wrapper .box {
width: 100%;
position: relative;
}
#wrapper .header {
width: 100%;
position: absolute;
background: #2ecc71;
}
#wrapper .content {
width: 100%;
overflow: auto;
background: #27ae60;
}

Related

how to make side by side Divs (with <p> inside) as a 2-column table

I am trying to make a side-by-side table with 2 divs column, that contains many <p> elements inside.
That would be easy if these two Divs and their contents are horizontal, but in this case, they are vertical, two sides' heights are not the same.
Is there any way to do it without using JavaScript?
*EDIT:
The reason I put two separate divs side by side is that I put new content to them using JavaScript Prepend.
On the left side are the English texts, and on the right side are translated texts.
It would be easier for me if the English texts were together inside a div and the same for the translated texts.
I have done it by using Javascript and setting one side's style. height = the other side's clientHeight, it would be much better if I was able to do this with only CSS and HTML
for (let i = 0; i < document.querySelectorAll('#div1 p').length; i++) {
document.querySelectorAll('#div1 p')[i].style.height = "auto";
document.querySelectorAll('#div2 p')[i].style.height = "auto";
if (document.querySelectorAll('#div1 p')[i].clientHeight > document.querySelectorAll('#div2 p')[i].clientHeight )
{
document.querySelectorAll('#div2 p')[i].style.height = document.querySelectorAll('#div1 p')[i].clientHeight-3+'px'
}
else
{
document.querySelectorAll('#div1 p')[i].style.height = document.querySelectorAll('#div2 p')[i].clientHeight-3+'px'
}
}
body {
font-family: Consolas,Menlo,"courier new",monospace;
font-size: 18px;
}
.grid-container {}
#div1{
width: 50%;
display: table-cell;
}
#div2{
width: 50%;
display: table-cell;
}
p{
margin-top: 0px;
padding-bottom: 3px;
padding-left: 3px;
margin-bottom: 6px;
border-bottom: 1px dashed #0000ff00;
border-color: gray;
}
<div class="grid-container">
<div id="div2" class="skiptranslate">
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley.</p>
<p> the second cell</p>
<p> the 3rd cell </p>
<p> the 4th cell </p>
</div>
<div id="div1" >
<p> I want this cell's height same as the left "lorem ipsum" cell </p>
<p> the second cell</p>
<p> the 3rd cell</p>
</div>
</div>
Here how i would do it, with rows taking 100% and cells taking 50%
.cell {
width: 50%
}
.row {
width: 100%;
height: auto;
display: flex;
margin-top: 0px;
padding-bottom: 3px;
padding-left: 3px;
margin-bottom: 6px;
border-bottom: 1px dashed #0000ff00;
border-color: gray;
}
body {
font-family: Consolas, Menlo, "courier new", monospace;
font-size: 18px;
}
<div class=" grid-container">
<div class="row">
<div class="cell">
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley.</p>
</div>
<div class="cell">
<p> I want this cell's height same as the left "lorem ipsum" cell </p>
</div>
</div>
<div class="row">
<div class="cell">
<p> the second cell</p>
</div>
<div class="cell">
<p> the second cell</p>
</div>
</div>
<div class="row">
<div class="cell">
<p> the 3rd cell </p>
</div>
<div class="cell">
<p> the 3rd cell </p>
</div>
</div>
<div class="row">
<div class="cell">
<p> the 4th cell </p>
</div>
<div class="cell"></div>
</div>
</div>
just to add to LK77s good answer - is there any reason why you can't just use a <table> element here? That's the simplest solution.
failing that, a more modern solution is to refactor the HTML to take out the column divs, then you could use display: flex or display: grid to accomplish this:
.flex-table {
display: flex;
flex-wrap: wrap;
width: 600px;
border: 1px solid;
}
.flex-table p {
margin: 0;
flex: 0 0 50%;
max-width: 50;
}
.grid-table {
display: grid;
grid-template-columns: repeat(2, 1fr);
width: 600px;
border: 1px solid;
}
.grid-table p {
margin: 0;
padding: 5px;
}
/**
Just to show the different columns
**/
.table p:nth-child(2n) {
background-color: rgba(255,0,0,.5);
}
<div class="flex-table table">
<p>Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum</p>
<p>Lorem ipsum second cell</p>
<p>Lorem ipsum third cell</p>
<p>Lorem ipsum fourth cell</p>
<p>Lorem ipsum fifth cell</p>
<p>Lorem ipsum sixth cell</p>
</div>
<div style="margin-bottom: 30px"></div>
<div class="grid-table table">
<p>Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum</p>
<p>Lorem ipsum second cell</p>
<p>Lorem ipsum third cell</p>
<p>Lorem ipsum fourth cell</p>
<p>Lorem ipsum fifth cell</p>
<p>Lorem ipsum sixth cell</p>
</div>

Problems with Sticky effect on Navbar

I am facing problems with sticky navbar on my website.
I used the code of w3schools for this navbar. The problem is that sticky effect on nav menu does not work at all. Menu just disappers during scrolling.
Link to my website
Here is how nav menu looks like:
CSS:
.sticky {
position: fixed;
top: 0;
width: 100%;
}
.sticky + .content {
padding-top: 60px;
}
<script>
window.onscroll = function() {myFunction()};
var navbar = document.getElementById("navbar");
var sticky = navbar.offsetTop;
function myFunction() {
if (window.pageYOffset >= sticky) {
navbar.classList.add("sticky")
} else {
navbar.classList.remove("sticky");
}
}
</script>
You have to set the sticky code on the container to apply, not directly on the navbar. As sticky works only for siblings and not the whole page.
<div class="col-lg-12" style="
position: sticky;
z-index: 1;
top: 0;
">
<br>
<div id="navbar-complex" class="scrollmenu tab-content nav nav-tabs">
This way it works. after you have some z-index problem but this is different
#id1, #id2{
width: 50%;
float:left;
}
#id1{
background: lightgreen;
}
#id2{
background: lightblue;
}
#id1 nav{
position: sticky;
top:0;
z-index:1;
}
#id2 .navContainer{
position: sticky;
top:0;
z-index:1;
}
nav{
background: lightgray;
}
.content{
width: 100%;
height: 500vh;
}
<div id="id1">
<h1>What you are doing</h1>
<div class="navContainer">
<nav>I am supposed to be sticky</nav>
</div>
<div class="content">
Lorem ipsum
<br>
Lorem ipsum
<br>
Lorem ipsum
<br>
Lorem ipsum
<br> Lorem ipsum
<br>
Lorem ipsum
<br>
Lorem ipsum
<br>
Lorem ipsum
<br>
Lorem ipsum
<br>
Lorem ipsum
<br> Lorem ipsum
<br>
Lorem ipsum
<br>
Lorem ipsum
<br>
Lorem ipsum
<br>
</div>
</div>
<div id="id2">
<h1> What you want</h1>
<div class="navContainer">
<nav>I am sticky</nav>
</div>
<div class="content">
Lorem ipsum
<br>
Lorem ipsum
<br>
Lorem ipsum
<br>
Lorem ipsum
<br> Lorem ipsum
<br>
Lorem ipsum
<br>
Lorem ipsum
<br>
Lorem ipsum
<br>
Lorem ipsum
<br>
Lorem ipsum
<br> Lorem ipsum
<br>
Lorem ipsum
<br>
Lorem ipsum
<br>
Lorem ipsum
<br>
</div>
</div>

CSS Full Height with divs distributing left space

I am building a message box with title, description, and answers.
I have been struggling for days with that, even played with a Codepen, but can't figure to handle this correctly.
I need:
Title to expand to a maximum of 300px before scrolling
Description to expand to a maximum to left space if no answer (or few), distribute space say 80% of space otherwise (I will add a button to hide this space) before scrolling also
Fixed height for message number title
Messages div to expand to a maximum space left
Input area to stay at bottom and able to size up if any user input (again let's say 20% before scrolling?)
Codepen link
<div class="demoContainer">
<div class="page">
<div class="title">
<h1>My awesome title that is so long i will move everything down</h1>
<button>Some stuff to click</button>
</div>
<div class="row">
<div class="colLeft">
<div class="description">
<h2>Author</h2>
<p>lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsumlorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsumlorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsumlorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsumipsum lorem ipsum lorem ipsum lorem ipsumlorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsumipsum lorem ipsum lorem ipsum lorem ipsumlorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsumipsum lorem ipsum lorem ipsum lorem ipsumlorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum </p>
</div>
<div class="between">
<p>Answers</p>
</div>
<div class="messages">
<ul>
<li>
toto
</li>
<li>
tAta
</li>
<li>
tAta
tAta
</li>
<li>
tAta
</li>
<li>
tAta
</li>
<li>
tAta
</li>
>
<li>
tAta
</li>
>
<li>
tAta
</li>
>
<li>
tAta
</li>
>
<li>
tAta
</li>
</ul>
</div>
<div class="input">
<textarea placeholder="Input height adapt to size until a maximum"></textarea>
</div>
</div>
<div class="colRight">
<ul>
<li>
some
</li>
<li>
stuff
</li>
</ul>
</div>
</div>
</div>
<div class="divider"></div>
<div class="page">
<div class="title">
<h1>My awesome short title</h1>
<button>Some stuff to click</button>
</div>
<div class="row">
<div class="colLeft">
<div class="description">
<h2>Author</h2>
<p>lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum </p>
</div>
<div class="between">
<p>Answers</p>
</div>
<div class="messages">
<ul>
<li>
toto
</li>
<li>
tAta
</li>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
</ul>
</div>
<div class="input">
<textarea placeholder="Input height adapt to size until a maximum"></textarea>
</div>
</div>
<div class="colRight">
<ul>
<li>
some
</li>
<li>
stuff
</li>
</ul>
</div>
</div>
</div>
</div>
* {
box-sizing: border-box;
}
.demoContainer {
display: flex;
flex-direction: row;
}
.divider {
width: 8px;
}
.page {
height: 600px;
width: 550px;
background-color: lightgrey;
display: flex;
flex-direction: column;
overflow: auto;
}
.title {
display: inline-flex;
justify-content: space-between;
align-items: center;
max-height: 200px;
}
.title button {
width: 90px;
height: 30px;
}
.row {
display: flex;
/*flex: 1 1 100%;*/
min-height: 0;
height: 100%;
}
.colLeft {
flex: 3 1 auto;
min-height: 0;
height: 100%;
border: 1px solid blue;
display: block;
flex-direction: column;
position: relative;
/*align-items: stretch;
align-content: stretch;*/
}
.description {
border: 1px dashed black;
/*flex: 4 1 100%;*/
max-height: 60%;
overflow: scroll;
}
.between {
border: 1px solid green;
height: 1, 1em;
}
.between>p {
margin: 0;
}
.messages {
border: 1px dashed red;
/*flex: 2 100 auto;*/
overflow: scroll;
}
ul {
max-width: 100%;
}
.input {
width: 100%;
min-height: 1rem;
flex: 1 1 3rem;
display: flex;
border: 1px solid yellow;
position: relative;
bottom: 0;
}
.input>textarea {
width: 100%;
}
.colRight {
flex: 1 1 auto;
border: 1px solid black;
min-width: 150px;
overflow: scroll;
}
The one on the right is a short example of what I would like, but remove <br/> to see the problem.
I tried with display: grid, isplay: block display: flex. I can't seem to find anything satisfying my needs.
My question is: is that even possible? With CSS only?
For everyone wondering, i discovered a few things while digging into css.
First of all is you can set a 100% height on a div to take up the free space if another element is in, but if and only if you set the parent element display: flex; !
With that in mind, it comes easier.
After that, I decided to dive into JS as my problem does not seem to be solvable with CSS only.
I took advantage of the "new" position: sticky; property, and my JS can take care of position it top: 0; or bottom: 0; depending on the scrolling position.
CSS Added :
.stickyBottom{
position: sticky;
bottom: 0;
}
.stickyTop{
position: sticky;
top: 0;
}
JS Code added:
var colLeft = document.getElementsByClassName("messagesInput")[0];
colLeft.onscroll = function(){myFunction()};
// Get the navbar
var between = document.getElementsByClassName("between")[0];
var desc = document.getElementsByClassName("description")[0];
// Get the offset position of the navbar
var sticky = between.offsetTop;
//between.classList.remove("stickyBottom")
function myFunction() {
if (colLeft.scrollTop >= sticky) {
between.classList.remove("stickyBottom")
between.classList.add("stickyTop")
} else {
between.classList.add("stickyBottom")
between.classList.remove("stickyTop");
}
}
It ends up in a way better UX than I initially wanted ! :)
CodePen Link updated accordingly.

CSS class orders shows different results

The bb class background colour would be red if I move the code before the intro-block class css codes , however if I put it after the intro-block class css codes the colour is not changing and nothing happens!
Could anyone tell me why this happens?!
.left-column {
width: 35%;
margin-left: 20px;
margin-right: 50px;
float: left;
overflow: hidden;
}
.right-column {
overflow: hidden;
}
.intro-block {
background-color: #22AAA1;
margin: 0 auto;
/*max-width: 950px;*/}
}
.bb {
background-color: red;
}
<body>
<header>
<section class="intro-block">
<div class="left-column">
<img class="profile-pic right-column" src="img/11.jpg">
</div>
<div class="right-column">
<h1>lorem ipsum</h1>
<p>
<h4>lorem ipsum</h4>
</p>
</div>
</section>
</header>
<main>
<section class="bb">
<h3>lorem ipsum</h3>
<div class="left-column">
<div>
<p>lorem ipsum</p>
</div>
</div>
<div class="right-column">
<h5>lorem ipsum</h5>
</div>
You have an extra } just before .bb {}
Note: don't wrap headings (h1 to h6) in p
You should indent/tidy your code for better reading and with that you will find this mistakes easily
.left-column {
width: 35%;
margin-left: 20px;
margin-right: 50px;
float: left;
overflow: hidden;
}
.right-column {
overflow: hidden;
}
.intro-block {
background-color: #22AAA1;
margin: 0 auto;
/*max-width: 950px;*/
}
.bb {
background-color: red;
}
<body>
<header>
<section class="intro-block">
<div class="left-column">
<img class="profile-pic right-column" src="img/11.jpg">
</div>
<div class="right-column">
<h1>lorem ipsum</h1>
<h4>lorem ipsum</h4>
</div>
</section>
</header>
<main>
<section class="bb">
<h3>lorem ipsum</h3>
<div class="left-column">
<div>
<p>lorem ipsum</p>
</div>
</div>
<div class="right-column">
<h5>lorem ipsum</h5>
</div>
</section>
</main>
/max-width: 950px;/}
you have an extra } after the quoted line that messes up with the following rules ...

vertical align bottom for a specific child

I have a parent element that has 2 children. I want to move 1st child to top, and second one to bottom. The parent element has a scroll and its children size isn't fixed. Children size expands dynamically depending on theirs content
So If theirs size are smaller than parent's one they would look like in the left picture, else they should expand parents div like in the right picture. Usually to move element to edges I'd use absolute position like this:
.parent {
position: relative;
}
.top-child {
position: absolute;
top: 0;
}
.bottom-child {
position: absolute;
bottom: 0;
}
But this case brakes the flow. Parent width and height wouldn't adjust depending by children size. Another solution is to use vertical-align
.parent {
display: table-cell;
vertical-align: bottom;
}
But in this scenario all children would move to bottom.
Here's jsfiddle. Green background is parent. topdiv and bottomdiv and childrens.
How should I CSS divs to attach children to edges without breaking the flow?
you can achieve this use display:table and table-row:
#scroller {
height:300px; /* this height is the min height before you want to scroll */
overflow:auto;
}
.table {
min-height:100%;
width:100%;
display:table;
}
.row {
display:table-row;
}
.row:first-child {
height:100%; /* this is needed to "push" the second row to the bottom (it will actually be 100% minus the bottom row height */
background:blue;
}
.row:last-child {
background:green;
}
<div id="scroller">
<div class="table">
<div class="row">expands to fill space</div>
<div class="row">stays at bottom</div>
</div>
</div>
Example fiddle
Fiddle with content and scrolling
Update
Applying my styles to your fiddle
Something like this?
.main {
width: 300px;
height: 300px;
overflow-y: auto;
border: 1px solid #999;
margin-bottom: 30px;
}
.parent {
min-height: 100%;
display: flex;
flex-direction: column;
}
.child-a {
flex: 1;
background: #ccc;
}
.child-b {
background: #ddd;
}
<div class="main">
<div class="parent">
<div class="child-a">
<p>Lorem ipsum dolor</p>
<p>Lorem ipsum dolor</p>
<p>Lorem ipsum dolor</p>
<p>Lorem ipsum dolor</p>
<p>Lorem ipsum dolor</p>
<p>Lorem ipsum dolor</p>
<p>Lorem ipsum dolor</p>
<p>Lorem ipsum dolor</p>
<p>Lorem ipsum dolor</p>
<p>Lorem ipsum dolor</p>
<p>Lorem ipsum dolor</p>
<p>Lorem ipsum dolor</p>
<p>Lorem ipsum dolor</p>
<p>Lorem ipsum dolor</p>
<p>Lorem ipsum dolor</p>
</div>
<div class="child-b">
<p>Amet ipsum dolor</p>
</div>
</div>
</div>
<div class="main">
<div class="parent">
<div class="child-a">
<p>Lorem ipsum dolor</p>
<p>Lorem ipsum dolor</p>
<p>Lorem ipsum dolor</p>
<p>Lorem ipsum dolor</p>
<p>Lorem ipsum dolor</p>
</div>
<div class="child-b">
<p>Amet ipsum dolor</p>
</div>
</div>
</div>