Is there a way for stickies to take into account other stickes on the page?
For example:
body {
display: flex;
min-height: 2000px;
flex-direction: column;
}
#header {
height: 40px;
flex: 0 0 auto;
position: sticky;
top: 0;
background: yellow;
}
#footer {
flex: 0 0 auto;
height: 20px;
}
#main {
display: flex;
flex: auto;
background: blue;
}
#side {
width: 200px;
background: red;
}
#side > div {
position: sticky;
top: 0px;
}
<div id="header">header</div>
<div id="main">
<div id="side">
<div>side</div>
</div>
<div id="content">
content
</div>
</div>
<div id="footer">footer</div>
Notice that if I scroll down the header will overlap the sidebar because they have the same top position.
To fix I have to make the top position of the sidebar take the value of the header height
body {
display: flex;
min-height: 2000px;
flex-direction: column;
}
#header {
height: 40px;
flex: 0 0 auto;
position: sticky;
top: 0;
background: yellow;
}
#footer {
flex: 0 0 auto;
height: 20px;
}
#main {
display: flex;
flex: auto;
background: blue;
}
#side {
width: 200px;
background: red;
}
#side > div {
position: sticky;
top: 40px;
}
<div id="header">header</div>
<div id="main">
<div id="side">
<div>side</div>
</div>
<div id="content">
content
</div>
</div>
<div id="footer">footer</div>
But what if the header has variable height? Can I tell the browser somehow to position the stickies so they dont overlap others?
I think you would need to use javascript for this. First to get the height of the header and then set the top position of your side div using that value. I am not aware of any pure css way of doing it I am afraid.
If you are using jQuery it is simply using the .height() method if not you can use this:
var clientHeight = document.getElementById('myDiv').clientHeight;
var offsetHeight = document.getElementById('myDiv').offsetHeight;
The offset method gets the height with any padding and borders.
Related
Consider the following:
* {padding: 0; margin: 0; }
body {
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
}
header {
flex: 0 0 50px;
background-color: lightgray;
}
div#wrapper {
flex: 1 0 0px;
display: flex;
flex-direction: row;
}
aside {
background-color: darkgray;
flex: 0 0 50px;
}
main {
display: block;
flex: 1 1 0px;
background-color: aliceblue;
}
div#content {
width: 60px;
height: 2000px;
margin: 10px;
background-color: red;
}
div#content-wrap {
width: 100%;
height: 100%;
}
div#content-container {
height: 100%;
overflow-y: scroll;
}
<html>
<head></head>
<body>
<header></header>
<div id="wrapper">
<aside></aside>
<main>
<div id="content-wrap">
<div id="content-container">
<div id="content"></div>
</div>
</div>
</main>
</div>
</body>
</html>
In the snippet above, the <body> fills all the available space, it's consisted of a <header> which takes an arbitrary height and a <div id="wrapper"> that takes the rest of available height. The aforementioned "#wrapper" has a "sidebar" that has an arbitrary width and a "<main>" section to take the rest of the width. I want only the "main" section to be scrollable, but applying a long enough "#content" causes the "body" to get the scrollbar, instead! (while I've enforced the heights to be 100%) So, how to fix this?
here only remove same height according to <header></header> from <div id="wrapper"> bcz of normaly it will take 100% height #wrapper so only add height: calc(100% - 50px);
div#wrapper {
flex: 1 0 0px;
display: flex;
flex-direction: row;
height: calc(100% - 50px);
}
and it will be working like below ss
I want to center a div and it's text, in a 100%-screen-width div, which is in a smaller wrapper.
.wrapper {
height: 800px;
width: 900px;
margin: auto;
background-color: #000000;
}
.box-wrapper {
width: 1000%;
position: relative;
left: -500%;
background-color: #FF6600;
}
.box {
background-color: #FF0000;
width: 600px;
position: relative;
left: 50%;
color: #00FF00;
}
span {
text-align: center;
display: block;
}
<div class="wrapper">
Random text for wrapper-div
<div class="box-wrapper">
<div class="box">
<span>ABC</span>
<span>DEF</span>
<span>GHI</span>
</div>
</div>
</div>
This code is kind of working but not perfect.
The red div should be moved a bit to the right, also the way
of doing it is not the best in my opinion.
I want a more robust and responsive solution.
To be more clear, it's for the pink division on the bottom
of this website: http://ndvibes.com
There the code is working 99% of the times and reponsive. But on some computers/screens it's 50% off. So I want a less-hacky (without transform etc) and more standard, robust way of getting that effect.
Wrapper 900px > 100%-screen-width coloured div > Centered text in that coloured div.
How can I achieve this the best as possible?
Thanks!
How about this approach, using absolute positioned pseudo elements. The outer-space div with overflow:hidden is to prevent a horizontal scroll bar appearing. I have added padding-top to the .wrapper just so you can see the snippet running in full screen mode.
body {
margin:0;
}
.outer-space {
overflow: hidden;
padding-top:80px;
}
.wrapper {
height: 800px;
width: 100%;
max-width: 900px;
margin: auto;
background-color: #000000;
}
.box {
background-color: #8904B1;
margin:0 auto;
color: #ffffff;
position: relative;
z-index: 2;
padding:10px 0;
}
.box-wrapper {
position: relative;
width:100%;
max-width: 600px;
margin:0 auto;
}
.box-wrapper:before, .box-wrapper:after {
content:"";
position: absolute;
height:100%;
width:100vw;
background-color: #8904B1;
top: 0;
z-index: 1;
}
.box-wrapper:before {
left:-100%;
}
.box-wrapper:after {
right:-100%;
}
span {
text-align: center;
display: block;
}
<div class="outer-space">
<div class="wrapper">
Random text for wrapper-div
<div class="box-wrapper">
<div class="box">
<span>Crazy full width window</span>
<span>absolute positioned pseudo elements</span>
<span>with centered content div and centered text thingy</span>
<span>all inside of a fixed width page wrapper!</span>
<br><span>““”̿ ̿ ̿ ̿ ̿’̿’̵͇̿̿з=(•̪●)=ε/̵͇̿̿/̿ ̿ ̿ ̿ ̿’““</span>
</div>
</div>
</div>
</div>
To center child element, add the following to the parent wrap will center all child.
display: flex;
align-items: center;
justify-content: center;
If you want 100% screen width, use viewport (100vw) for 100% screen width
viewport
The #viewport CSS at-rule contains a set of nested descriptors in a CSS block that is delimited by curly braces. These descriptors control viewport settings, primarily on mobile devices.
1vw = 1% of viewport width
1vh = 1% of viewport height
1vmin = 1vw or 1vh, whichever is smaller
1vmax = 1vw or 1vh, whichever is larger
REF: #viewport
REF: Viewport Sized Typography
body {
margin: 0;
}
.wrapper {
height: 800px;
width: 900px;
margin: auto;
background-color: #000000;
}
.box-wrapper {
width: 900px;
max-width: 900px;
position: relative;
background-color: #FF6600;
display: flex;
align-items: center;
justify-content: center;
}
.outer-wrapper {
width: 100vw;
display: flex;
align-items: center;
justify-content: center;
}
.box {
width: 80%;
background-color: #FF0000;
position: relative;
color: #00FF00;
}
span {
text-align: center;
display: block;
}
<div class="outer-wrapper">
<div class="wrapper">
<p>Random text for wrapper-div</p>
<div class="box-wrapper">
<div class="box">
<span>ABC</span>
<span>DEF</span>
<span>GHI</span>
</div>
</div>
</div>
</div>
It seems so simple, but I wrap my mind about it and googled a lot but couldn't find an answer:
Container with two vertical rows, one has height defined in pixels (header), and the other has image that should stretch as much as remaining height (slider div). The problem is that this height of header is dynamic (as in unknown) and we can't use that value in defining CSS of container or slider div.
How do I solve it without javascript?
<section>
<header style="height:40px; background: yellow;">header</header>
<div id="slider">
<img src="http://amanita-design.net/img/home-news/botanicula.jpg" />
</div>
</section>
section {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 400px;
background: green;
}
#slider {
height: 100%; /* this is wrong; how to set height to stretch element? */
}
img {
width: 100%;
height: 100%;
}
Header is set to 40px just for the sake of the example. It could be any other value, but the CSS definition of other elements shouldn't be aware of that, because it's dynamically loaded 3rd party component with inline CSS.
Also, slider div is a complex slider (Swiper) that renders code with bunch of nested divs but I need to use exactly that one.
But this DOM structure should be rough sketch of my case.
Example is here: https://jsfiddle.net/snaokLxd/3/
Set the parent to flex with #slider set to flex-grow: 1 (or flex: 1 0 0 for short)
section {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 400px;
background: green;
display: flex;
flex-direction: column;
}
#slider {
flex: 1 0 0;
}
img {
width: 100%;
height: 100%;
vertical-align: top;
}
<section>
<header style="height:40px; background: yellow;">header</header>
<div id="slider">
<img src="http://amanita-design.net/img/home-news/botanicula.jpg" />
</div>
</section>
Flex example below:
* {
margin: 0;
}
section {
height: 100vh;
width: 400px;
background: green;
display: flex;
flex-direction: column;
}
#slider {
flex-grow: 2;
}
img {
display: block;
width: 100%;
height: 100%;
}
<section>
<header style="height:40px; background: yellow;">header</header>
<div id="slider">
<img src="http://amanita-design.net/img/home-news/botanicula.jpg" />
</div>
</section>
Also on JSFiddle.
I have a wrapper of 500px and 2 columns. The second column is 200px width (flex: 0 0 200px).
If in the first there is an element > 300px the first column will expand according to this element.
How can I stop the first column from growing, basing only the width of the wrapper and the second column?
Fiddle here: https://jsfiddle.net/b58aatdr/3/
#hello {
display: flex;
width: 500px;
}
#hello > div {
height: 50px;
}
#hello > div:first-child {
background-color: yellow;
}
#hello > div:last-child {
background-color: red;
flex: 0 0 200px;
}
#baddiv {
width: 400px;
height: 20px;
background-color: purple;
}
<div id="hello">
<div>
<div id="baddiv"></div>
</div>
<div></div>
</div>
Set max-width: 300px to your first div if you want it to adjust itself up to 300px and use width: 300px; if you want it to always be 300px even if content is less wide.
Update based on comment
The 2:nd div group uses another trick, position: absolute, where one doesn't need to set any width, it uses the parent and the right div to restrict the left div from growing beyond the 300px.
Note also, this is a normal behavior how element works, if they don't have a fixed/max width set, they grow (or in some cases wrap) to fit their content.
Update 2 based on comment
The 3:rd div group uses display: table instead of flex, where one doesn't need to set any width.
.hello {
display: flex;
width: 500px;
}
.hello > div {
height: 50px;
}
.hello > div:last-child {
background-color: red;
flex: 0 0 200px;
}
.baddiv {
width: 400px;
height: 20px;
background-color: purple;
}
/* alt. 1 */
.hello.nr1 > div:first-child {
background-color: yellow;
max-width: 300px;
}
/* alt. 2 */
.hello.nr2 > div:first-child {
flex: 1;
position: relative;
background-color: lime;
}
.inner {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
overflow: hidden;
}
/* alt. 3 */
.hello.nr3 {
display: table;
table-layout: fixed;
width: 500px;
}
.hello.nr3 > div {
height: 50px;
display: table-cell;
}
.hello.nr3 > div:first-child {
background-color: cyan;
}
.hello.nr3 > div:last-child {
background-color: red;
width: 200px;
}
<div class="hello nr1">
<div>
<div class="baddiv"></div>
</div>
<div></div>
</div>
<br>
<div class="hello nr2">
<div>
<div class="inner">
<div class="baddiv">
</div>
</div>
</div>
<div></div>
</div>
<br>
<div class="hello nr3">
<div>
<div class="baddiv"></div>
</div>
<div></div>
</div>
I'm trying to make a child div of a flexbox layout fill its parent. In any other context setting the width/height to 100% causes a div to fill its parent... I only wish to use flexbox for my top level layout.
Problems
#map-container div will not fill #col1 even though it has height 100% set.
#controls div appears outside #col1 completely. I've previously used absolute layout to align boxes to corners without problems. Being inside a flexbox grand-parent seems to cause issues.
What I'm expecting is #map-container and #map to fill #col1 and #controls to align to bottom right-hand corner of #map.
.wrapper, html, body {
height:100%;
margin:0;
}
#col1 {
display: flex;
}
#map-container {
background-color: yellow;
width: 100%;
height: 100%;
}
#map {
background-color: purple;
width: 100%;
height: 100%;
}
#controls {
background-color: orange;
position: absolute;
right: 3px;
bottom: 3px;
width: 100px;
height: 20px;
}
.wrapper {
display: flex;
flex-direction: column;
}
#row1 {
background-color: red;
}
#row2 {
flex:2;
display: flex;
}
#col1 {
background-color: green;
flex: 1 1;
}
#col2 {
background-color: blue;
flex :0 0 240px;
}
<div class="wrapper">
<div id="row1">Header</div>
<div id="row2">
<div id="col1">
<div id="map-container">
<div id="map">
Map
</div>
<div id="controls">Controls</div>
</div>
</div>
<div id="col2">Sidebar</div>
</div>
</div>
#map-container div will not fill #col1 even though it has height 100% set.
It won't work that way, because for a percentage unit to work, it needs to have height set on its parent all the way up. This fights against the flex model, where the flex-items are distributed and arranged by the flex-box layout and have no dimensions set. Why use a flex layout when all your elements are 100%? Either do a 100% on all your element all the way up, or do a flex on all containers.
If you stick to flex layout, then you will have to get into nested flex. Otherwise, you will get #map-container to fill-up, but not the #map.
This fiddle http://jsfiddle.net/abhitalks/sztcb0me illustrates that problem.
#controls div appears outside #col1 completely. I've previously used absolute layout to align boxes to corners without problems. Being
inside a flex-box grand-parent seems to cause issues.
The only issue is that you are positioning it absolutely, but in relation to what? You need to position your #map-container relatively for that to work.
Here is how:
Fiddle: http://jsfiddle.net/abhitalks/sztcb0me/1/
Snippet:
* { box-sizing: border-box; padding: 0; margin: 0; }
html, body, .wrapper { height:100%; width: 100%; }
.wrapper { display: flex; flex-direction: column; }
#row1 { flex: 0 1 auto; background-color: red; }
#row2 { flex: 2 0 auto; display: flex; }
#col1 { flex: 1 0 auto; display: flex; background-color: green; }
#col2 { flex: 0 0 240px; background-color: blue; }
#map-container {
flex: 1 0 auto; display: flex;
position: relative; background-color: yellow;
}
#map { flex: 1 0 auto; background-color: purple; }
#controls {
background-color: orange;
position: absolute;
right: 3px; bottom: 3px;
width: 100px; height: 20px;
}
<div class="wrapper">
<div id="row1">Header</div>
<div id="row2">
<div id="col1">
<div id="map-container">
<div id="map">
Map
</div>
<div id="controls">Controls</div>
</div>
</div>
<div id="col2">Sidebar</div>
</div>
</div>
the problem is that it's wrapped in #map-container
.wrapper, html, body {
height:100%;
margin:0;
}
#col1 {
display: flex;
}
#map-container {
background-color: yellow;
width: 100%;
height: 100%;
}
#map {
background-color: purple;
width: 100%;
/* height: 100%; */
display: flex;
flex-wrap: wrap-reverse;
justify-content: space-between;
}
#controls {
background-color: orange;
position: relative;
/*right: 3px;
bottom: 3px;*/
width: 100px;
height: 20px;
}
.wrapper {
display: flex;
flex-direction: column;
}
#row1 {
background-color: red;
}
#row2 {
flex:2;
display: flex;
}
#col1 {
background-color: green;
flex: 1 1;
}
#col2 {
background-color: blue;
flex :0 0 240px;
}
<div class="wrapper">
<div id="row1">Header</div>
<div id="row2">
<div id="col1">
<!-- <div id="map-container"> -->
<div id="map">
Map
<div id="controls">Controls</div> <!-- add it here -->
</div>
<!-- <div id="controls">Controls</div> -->
<!--</div> -->
</div>
<div id="col2">Sidebar</div>
</div>
</div>
adding an absolute position controls in that way is not optimal (in the snippet I commented it out) ; you can place the controlsnested in #map (and use flex properties for correcting placement)