I'm looking to display a sticky sidebar on my page, positioned relatively when the client is at the top of the document and fixed when the client scrolls.
My problem is with Safari (it seems to work fine with Chrome and Firefox).
I had it working with a set of floating divs (sidebar floats left) but when I changed to flexbox I found that fast scrolling was too fast for the sticky sidebar to keep up (whether detaching itself from its relative position or staying in a fixed position on the page.
Has anyone else encountered a similar issue and found a work around? I'll go back to floats if necessary but as I'm still learning this stuff it would be great to get to the bottom of why flexbox is causing problems.
Thanks! (Code/markup follows)
HTML:
<div class="order-form">
<div class="left-column" id="left-column">
<div class="sidebar" id="sidebar">
<ul id="courses"></ul>
</div>
</div>
<div class="menu" id="menu"><!-- content --></div>
<div class="right-column"> <!-- content --></div>
</div>
JQuery:
$(window).scroll(function() {
stickers();
});
function stickers() {
var sidebar = $(".sidebar");
if ($(window).scrollTop() > 300) {
sidebar.addClass("scrolling-sidebar");
} else {
sidebar.removeClass("scrolling-sidebar");
}
}
Old, unproblematic, CSS:
.order-form {
padding: 0 300px 0 120px;
}
.sidebar {
width: 150px;
font-weight: lighter;
text-transform: uppercase;
display: block;
}
.sidebar.scrolling-sidebar {
position: fixed;
top: 75px;
left: 5%
}
My current CSS file (compiled from Sass, with problems seemingly arising from my use of flexbox):
.order-form {
margin: 50px 0;
padding: 0 5%;
display: -webkit-box;
display: -webkit-flex;
display: -moz-flex;
display: -ms-flexbox;
display: flex;
-webkit-align-items: stretch;
align-items: stretch;
-webkit-flex-direction: row;
-moz-flex-direction: row;
flex-direction: row;
-webkit-flex-wrap: nowrap;
-moz-flex-wrap: nowrap;
flex-wrap: nowrap;
-webkit-justify-content: flex-start;
-moz-justify-content: flex-start;
justify-content: flex-start;
position: relative;
}
.order-form .left-column {
overflow: hidden;
display: -webkit-box;
display: -webkit-flex;
display: -moz-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-basis: 0;
-moz-flex-basis: 0;
flex-basis: 0;
-webkit-order: 1;
-moz-order: 1;
order: 1; }
#media (min-width: 992px) {
.order-form .left-column {
margin-right: 5%;
display: -webkit-box;
display: -webkit-flex;
display: -moz-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-basis: 100px;
-moz-flex-basis: 100px;
flex-basis: 100px;
}
}
Related
When I set flex-container height larger than what flex-items would occupy, items that wrap, have space between them. Mind you - justify-content and align-items are both set to flex-start. Here is snippet (click on full page after run)
.flex-container {
min-height: 100vh;
position: relative;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: flex-start;
flex-wrap: wrap;
}
header,
main,
aside,
footer {
padding: 1rem;
background-color: tomato;
}
header,
footer {
width: 100%;
}
main {
width: 75%;
}
aside {
flex-grow: 1;
}
<div class="flex-container">
<header>Header Content</header>
<main>Main content here.</main>
<aside>Sidebar content</aside>
<footer>Footer Content</footer>
</div>
Here's the pen
This can be reproduced with flex-direction: column; if you reversed all the properties. Is this expected behavior? If so, why? Is there a way I came around this and get something like that:
with the flex-container height set to 100vh ?
The correct answer without adding extra markup, is align-content: flex-start; - default is stretch, that's why wrapping elements have extra space between them, when the flex-container's size exceeds the size of the elements in it.
If I good understand your question - you can add following div .wrappper inside flex-container
.wrapper {
position: relative;
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-wrap: wrap;
flex-basis: 100%;
}
body {margin: 0}
.wrapper {
position: relative;
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-wrap: wrap;
flex-basis: 100%;
}
.flex-container {
min-height: 100vh;
position: relative;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: flex-start;
flex-wrap: wrap;
}
header,
main,
aside,
footer {
padding: 1rem;
background-color: tomato;
}
header,
footer {
width: 100%;
background-color: blue;
}
main {
flex-basis: 75%;
flex-grow: 1;
background-color: yellow;
}
aside {
flex-grow: 1;
}
<div class="flex-container">
<div class="wrapper">
<header>Header Content</header>
<main>Main content here.</main>
<aside>Sidebar content</aside>
<footer>Footer Content</footer>
</div>
</div>
Explanation what previous solution doesn't wokrs: because the height of your flex items was set to 1rem+font size, and the align-items: flex-start; was set so flex not change items height but put them on proper place (flex-start). But if you would use align-items: streth; then flex will stretch elements. Because you want to have 100vh for .flex-container, we need to use wrapper which was not stretched to full height of container because container has still align-items: flex-start;. And that wrapper height is sum of his chidren height without extra space.
How to fix specific CSS position scaling in percentages?
The jump occurs during manual scaling in the browser.
code:
jsfiddle: http://jsfiddle.net/y5b576cm/2/
Try avoiding using percentage in width and height as much as you can, they are very messy.
First of all, have your top containers with the same fixed width:
section.h-banner {
width: 66.444%;
position: relative;
margin: 0 auto;
left: -3.666%;
}
then align the child container
.container-header {
text-align: center;
margin: 0px -12%;
left: 12.7%;
position: relative;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
justify-content: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
}
but again, very messy..
In the attached Codepen, you will see that I am using Flexbox to align the Logo and Menu icons in the header. The logo should be aligned left, the menu icon right. (I have other elements but this is just a simplified version for demonstration).
When testing in IE11, I see that the Flexbox isn't working. As far as I can tell via the documentation, IE11 should be supporting this. I have other Flexbox elements, which are also not working.
As you can see, the prefix is added for IE10.
Is anyone able to tell me where I am going wrong here?
https://codepen.io/anon/pen/EWqvNv
Here is the CSS:
.container {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-justify-content: flex-end;
-ms-flex-pack: end;
justify-content: flex-end;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
}
.nav-logo {
margin-right: auto;
}
As IE11 is quite buggy, so if to remove the justify-content: flex-end;, it will work as intended
Updated codepen
.container {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
}
.nav-logo {
margin-right: auto;
width: 100px;
height: 50px;
background: #000;
}
<html>
<head></head>
<body>
<header>
<div class="container">
<a class="nav-logo" href=""></a>
<a class="nav-toggle" href="#">Menu</a>
</div>
</header>
</body>
</html>
Side note:
Based on the above left-to-right flow (omitted justify-content defaults to flex-start), I would use margin-left: auto on the nav-toggle instead, sample codepen
Setting justify-content: space-between seems to work; why not use that?
I'm Sorry but if you look at https://caniuse.com/#search=justify-content it's clear that IE doesn't support this method. To fixed that problem on IE you can use extra css like so:
.container {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
position: relative;
#supports(justify-content: space-between) {
-webkit-justify-content: flex-end;
-ms-flex-pack: end;
justify-content: flex-end;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
}
}
.nav-logo {
margin-right: auto;
width: 100px;
height: 50px;
background: #000;
}
.nav-toggle {
position: absolute;
right: 0;
top: 0;
#supports(justify-content: space-between) {
position: unset;
}
}
<html>
<head></head>
<body>
<header>
<div class="container">
<a class="nav-logo" href=""></a>
<a class="nav-toggle" href="#">Menu</a>
</div>
</header>
</body>
</html>
I have container with buttons on top of a map control. This control needs to be scrollable as there might be more buttons than the screen height allows for.
What I am looking for is a way to have the buttons to be displayed outside of the container which means that I can put the container off the screen to be invisible.
Or to have the scrollbar on the left hand side so that it is not between the map and the controls.
Here is some html
<div class='ctrl__scroll'>
<button class="map__interface mdl-button mdl-js-button mdl-button--fab mdl-button--colored">
<i class="material-icons">add</i>
</button>
<button class="map__interface mdl-button mdl-js-button mdl-button--fab mdl-button--colored">
<i class="material-icons">remove</i>
</button>
<button>...</button>
</div>
Here is the css
.ctrl__scroll {
position: absolute;
top: 0;
left: 0;
width: 90px;
height: 100%;
overflow-y: auto;
overflow-x: hidden;
background-color: rgba(0, 0, 0, 0.5);
}
.ctrl__scroll > .mdl-button {
margin-top: 10px;
margin-left: 10px;
}
Here is the jsFiddle for the screenshot.
https://jsfiddle.net/goldrydigital/zez3gz21/
Edit: I have now worked this out and changed the jsFiddle. I am using the excellent jScrollPane plugin which allows me to do whatever I want with scrollpanes.
Even if you could display the children outside their scrollable parent (which is counter-intuitive at best) I don't think you'd be able to scroll them. However, you can't have overflow-x:visible; overflow-y:auto; on the same an element. It will automatically add a scrollbar for the X asis too.
Let's take into account that most mobile devices have nice-looking, self-hiding semi-transparent bars, making your solution look good even with the scrollbar visible (as it is now). We only need to fix the scrollbar on non-touch devices. On desktop devices, which are rendering it ugly and opaque. Here's a possible solution:
#media (min-width: 768px) {
.ctrl__scroll > .mdl-button {
margin: 10px 0 0 10px;
}
.ctrl__scroll {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
-moz-box-orient: vertical;
-moz-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-pack: start;
-webkit-justify-content: flex-start;
-moz-box-pack: start;
-ms-flex-pack: start;
justify-content: flex-start;
overflow: visible;
background-color: transparent;
}
}
Add it at the end of your current CSS. Your updated jsFiddle.
Just add:
.map {
padding-left: 90px;
...
}
which is the size of your side menu
I'm using flexbox for a layout. My constraint is that the image must be situated at the middle.
I've made a minimal markup that reproduces the issue: http://codepen.io/anon/pen/xwNomN
It works perfectly well in all browsers EXCEPT on IE 10 and 11, where (as shown in the CodePen) a big amount of empty space is added at the top and bottom of the image.
.collection__list {
display: flex;
flex-wrap: wrap;
}
.product-item {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.product-item__figure {
position: relative;
display: flex;
align-items: center;
justify-content: center;
flex: 1 0 auto;
}
.product-item__figure > a {
display: flex;
position: relative;
flex: 1;
}
.product-item__image-wrapper {
position: relative;
width: 100%;
}
.product-item__image {
display: block;
margin: 0 auto;
max-width: 100%;
}
I've tried a lot of fixes, played with flex-shrink, flex-grow... but after 1 whole day lost, I'd love to know what I'm doing wrong.
Thanks
Oh... I've found it by chance. Adding overflow: hidden to product-item__figure made the trick....