Sticky nav on scroll acting weird in Safari - javascript

I coded a simple, one-page website for my parents from scratch, and I added a simple navigation menu below the hero that sticks when it reaches the top of the browser on scroll. It works flawlessly in Chrome and Firefox.
In Safari, the stick on scroll part works fine, but everything inside the navbar does this weird thing where it re-animates in from the left.
Here's the site: http://firstfruitsllc.com
Here's the little jQuery script and the CSS:
var mn = $(".nav");
mns = "nav-fixed";
hdr = $('header').height();
$(window).scroll(function() {
if ($(this).scrollTop() > hdr) {
mn.addClass(mns);
} else {
mn.removeClass(mns);
}
});
.nav {
border-bottom: 2px solid #eee;
position: relative;
background: white;
height: 100px;
margin-bottom: -100px;
box-sizing: border-box;
overflow: hidden;
transition: 0.2s ease-in-out;
}
.nav-fixed {
z-index: 999998;
width: 100%;
max-width: 1440px;
position: fixed;
top: 0;
transition: 0.2s ease-in-out;
-webkit-box-shadow: 0px 6px 10px -5px rgba(0, 0, 0, 0.08);
-moz-box-shadow: 0px 6px 10px -5px rgba(0, 0, 0, 0.08);
box-shadow: 0px 6px 10px -5px rgba(0, 0, 0, 0.08);
}
.nav-fixed:before {
z-index: 999999;
content: '';
display: block;
position: absolute;
width: 150px;
height: 50px;
top: 25px;
left: 25px;
background-image: url('https://dl.dropboxusercontent.com/s/uezydedqpo55ub2/first-fruits-logo-color.svg?raw=1');
background-size: contain;
background-position: center;
background-repeat: no-repeat;
transition: all 0.5s ease-in-out;
}
Thanks!

It looks like safari is having a hard time with the transition of no widths being declared to having both declared as it goes to fixed. Try this:
.nav
{
width: 100%;
max-width: 1440px;
}

The issue occurs because new animatable properties are being added when the .nav-fixed class is added. Specifically width and max-width. To prevent this you can add
width: 100%;
max-width: 1440px;
to the .nav class.

When you add width: 100% to .navigation, the glitch is gone. I cannot explain why Safari behaves so odd though.

Related

CSS Frosted glass look without backdrop-filter but including radial-gradient

Im trying to implement a design for Anki cards, I made in Figma, in CSS.
This site does a great job explaining how to accomplish the background blur without backdrop-filter (not supported in Anki). But so far I was not able to figure out how to add a radial-gradient over the background image before I blur it (to add a directional light effect).
The main Problem seems to be the fact that background: inherit; is used to align the background images. And I don't quite get how to align them without the inherit option.
So, is there a way to get the gradient "included" in the blur?
Here is the code from the tutorial (in case the link breaks). And this is the codepen.
body {
background: url(https://images.unsplash.com/photo-1544306094-e2dcf9479da3) no-repeat;
/* Keep the inherited background full size. */
background-attachment: fixed;
background-size: cover;
display: grid;
align-items: center;
justify-content: center;
height: 100vh;
}
.container {
width: 30rem;
height: 20rem;
box-shadow: 0 0 1rem 0 rgba(0, 0, 0, .2);
border-radius: 5px;
position: relative;
z-index: 1;
background: inherit;
overflow: hidden;
}
.container:before {
content: "";
position: absolute;
background: inherit;
z-index: -1;
top: 0;
left: 0;
right: 0;
bottom: 0;
box-shadow: inset 0 0 2000px rgba(255, 255, 255, .5);
filter: blur(10px);
margin: -20px;
}
<div class="container"></div>
Use CSS variable to store the image and be able to add your gradient:
body {
--img: url(https://images.unsplash.com/photo-1544306094-e2dcf9479da3);
background: var(--img) center/cover fixed no-repeat;
display: grid;
place-items:center;
height: 120vh;
}
.container {
width: 30rem;
height: 20rem;
box-shadow: 0 0 1rem 0 rgba(0, 0, 0, .2);
border-radius: 5px;
position: relative;
z-index: 1;
overflow: hidden;
}
.container:before {
content: "";
position: absolute;
background:
radial-gradient(transparent, red), /* your background here */
var(--img) center/cover fixed no-repeat;
z-index: -1;
inset:0;
box-shadow: inset 0 0 2000px rgba(255, 255, 255, .5);
filter: blur(10px);
margin: -20px;
}
<div class="container"></div>

Creating inset shadow within scrollable region but above internal divs

I have a paper-dialog-scrollable of which I would like a shadow to appear at the top when scrolling down the page.
However, if I set an inset box shadow, any internal divs simply go over the top of it even after playing with z-index.
Can anybody help me? Please see this Fiddle to play/edit.
The aim is to have no shadow when content hasn't been scrolled, then fade in when it is.
You need to make one more class boxShadow to define box-shadow on scrolling div.
.container {
width: 400px;
height: 200px;
background: #e5e5e5;
overflow: auto;
}
.content {
text-align: center;
width: 200px;
height: 300px;
background: lightblue;
margin: auto;
margin-top: 20px;
margin-bottom: 20px;
padding: 10px;
z-index:-1;
}
.boxShadow{box-shadow: inset 0 10px 10px -1px rgba(0,0,0,0.6); width:400px; height:20px; background:#e5e5e5;}
<div class="boxShadow"></div>
<div class="container">
<div class="content">
Some text
</div>
</div>
You need to add JQuery:
var header = $(".container");
$(".container").scroll(function() {
var scroll = $(this).scrollTop();
if (scroll >= 2) {
$(this).addClass("shadow");
} else {
$(this).removeClass("shadow");
}
});
.container {
width: 400px;
height: 200px;
background: #e5e5e5;
overflow: auto;
-webkit-transition: all 0.2s ease;
-moz-transition: all 0.2s ease;
-o-transition: all 0.2s ease;
transition: all 0.2s ease;
}
.container.shadow {
box-shadow: inset 0 10px 10px -1px rgba(0,0,0,0.6);
-webkit-transition: all 0.2s ease;
-moz-transition: all 0.2s ease;
-o-transition: all 0.2s ease;
transition: all 0.2s ease;
}
.content {
text-align: center;
width: 200px;
height: 300px;
background: lightblue;
margin: auto;
margin-top: 20px;
margin-bottom: 20px;
padding: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="container">
<div class="content">
Some text
</div>
</div>
Use negative z-index and position: relative on the .content to move it under the .container, and add a .wrapper with the background color, position: relative, and a positive z-index value to provide background under the .content.
var container = document.querySelector('.container');
var containerClasses = container.classList;
container.addEventListener('scroll', function(e) {
if(e.target.scrollTop > 0) {
containerClasses.contains('shadow') || containerClasses.add('shadow');
} else {
containerClasses.remove('shadow');
}
});
.wrapper {
position: relative;
z-index: 0;
display: inline-block;
background: #e5e5e5;
}
.container {
position: relative;
width: 400px;
height: 200px;
overflow: auto;
box-shadow: inset 0 10px 10px -1px rgba(0, 0, 0, 0);
transition: box-shadow 0.3s;
}
.shadow {
box-shadow: inset 0 10px 10px -1px rgba(0, 0, 0, 0.6);
}
.content {
position: relative;
z-index: -1;
text-align: center;
width: 200px;
height: 300px;
background: lightblue;
margin: auto;
margin-top: 20px;
margin-bottom: 20px;
padding: 10px;
}
<div class="wrapper">
<div class="container">
<div class="content">
Some text
</div>
</div>
</div>
If you need the .content to be clickable you can add a wrapper with a pseudo element overlay. The overlay has pointer-events: none, which means that the content under it can be clicked. The only problem is the width of the scrollbar, which is not consistent across browsers:
var wrapperClasses = document.querySelector('.wrapper').classList;
var container = document.querySelector('.container');
container.addEventListener('scroll', function(e) {
if(e.target.scrollTop > 0) {
wrapperClasses.contains('shadow') || wrapperClasses.add('shadow');
} else {
wrapperClasses.remove('shadow');
}
});
.wrapper {
position: relative;
display: inline-block;
background: #e5e5e5;
}
.wrapper::before {
position: absolute;
z-index: 1;
top: 0;
width: calc(100% - 12px); /** the width minus the scrollbar width **/
height: 100%;
box-shadow: inset 0 10px 10px -1px rgba(0, 0, 0, 0.6);
opacity: 0;
pointer-events: none;
transition: opacity 0.3s;
content: "";
}
.shadow::before {
opacity: 1;
}
.container {
width: 400px;
height: 200px;
overflow: auto;
}
.content {
text-align: center;
width: 200px;
height: 300px;
background: lightblue;
margin: auto;
margin-top: 20px;
margin-bottom: 20px;
padding: 10px;
}
<div class="wrapper">
<div class="container">
<div class="content">
Some text
</div>
</div>
</div>

Div appearing in center breaks if user has scrolled

I have the body/html of my page set up like this with CSS:
body, html {
height: 100%;
margin: 0px;
padding: 0px;
font-family: Segoe, Segoe UI, DejaVu Sans, Trebuchet MS, Verdana, " sans-serif";
font-size: 14px;
display: flex;
flex-direction: column;
background: #282828;
min-width: 100%;
min-height: 100%;
}
I then have a popup that I occasionally append to the page (body) using JQuery. This popup is DIV as follows:
.error_popup_container {
width: 400px;
height: auto;
padding: 10px;
background: #454545;
border: solid #fafafa 2px;
border-radius: 1px;
z-index: 3;
position: absolute;
-webkit-box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.75);
-moz-box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.75);
box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.75);
left: 50%;
top: 50%;
margin: -50px 0 0 -200px; /* 50px = half of height, 140px = half of width */
}
The issue is that the div only appears in the middle of the page if the user hasn't scrolled.
If the user has scrolled the div will be out of view.
I need the div to appear in the middle of the page no matter how far they have scrolled. Any ideas?
I've played around a ton but haven't found the cause. I'm sure it's something simple.
Agree with the position: fixed; and to keep it centered, I would use:
/*modal-wrapper*/ {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
If the modal will ever be longer than a small viewport, you could add a media query breakpoint with an overflow-y: scroll; property.
I think you probably just want to use position: fixed

Dynamically position absolute element on game map

I found myself stuck with this problem: I have game map with following code
Code
.content-right {
width: 50%;
height: 100%;
position: relative;
align-self: auto;
background-color: #44362D;
}
.content-inner-top {
width: 100%;
height: 70%;
background-image: url("http://i.imgur.com/wLJ1Pnt.jpg"); /* map.png */
background-position: left center;
background-size: 100% auto;
-moz-user-select: none;
background-repeat: no-repeat;
box-sizing: border-box;
position: relative;
-webkit-box-shadow: inset 0px 0px 35px 11px rgba(0, 0, 0, 0.75);
-moz-box-shadow: inset 0px 0px 35px 11px rgba(0, 0, 0, 0.75);
box-shadow: inset 0px 0px 35px 11px rgba(0, 0, 0, 0.75);
}
.content-inner-bottom {
width: 100%;
height: 30%;
margin: 0 auto;
z-index: 9;
text-align: center;
display: block;
position: relative;
top: 10%;
transform: translateY(-10%);
}
#position {
width: 4%;
height: 6.11979%;
background-color: #FF503C;
border: 3px solid #90EE90;
box-shadow: 0px 0px 35px #87CEEB;
position: relative;
border-radius: 50%;
transform: scaleY(0.75);
left: 85%;
top: 200px;
}
<div class="content-right">
<div class="content-inner-top">
<div id="position"></div>
</div>
<div class="content-inner-bottom"></div>
</div>
I would like to absolute position #position element on game map, but, I find it impossible because every time I resize browser window height, element goes to another place. Images are shown below.
Images
1st image (normal window)
2nd image (resized window)
What should I do? I cannot find solution via javascript nor jQuery either...
Thanks for your help in advance
I see that there's a top in 'px' but when you decrease the size of window, the image is smaller not only in width but also height. That's why the pointer went down.
The percentage 'left' property seems to work fine. If you want to use also percents for 'top' property (which could solve the problem), you have to explicitly define the height of the element (the image in your case). You can do that with jQuery for example most easily like this (given that you have an #image element):
$('#image').height($('#image').height());
Then you can add a resize handler and reassign new height. You may have to remove the previous height, so the whole would be something like this:
$(window).resize(function() {
$("#image").css("height","");
$('#image').height($('#image').height());
});
Then you should be able to use css top property in percents and it would be working after window resize.
You will need to modify your layout in order to achieve this behavior
First of all you need to add your map as an img and created a holder for it
<div class="content-right">
<div class="content-inner-top">
<div class="map-holder">
<img src="http://i.imgur.com/wLJ1Pnt.jpg" class="content-inner-map" />
<div id="position"></div>
</div>
</div>
<div class="content-inner-bottom"></div>
</div>
After that it is a matter of css:
added
.content-inner-map {
resize: both;
width: 100%;
}
.map-holder {
position: relative;
top: 50%;
display: block;
transform: translateY(-50%);
}
.content-inner-top:after {
position: absolute;
-webkit-box-shadow: inset 0px 0px 35px 11px rgba(0, 0, 0, 0.75);
-moz-box-shadow: inset 0px 0px 35px 11px rgba(0, 0, 0, 0.75);
box-shadow: inset 0px 0px 35px 11px rgba(0, 0, 0, 0.75);
top:0;
left:0;
right:0;
bottom:0;
content:"";
}
Altered
.content-inner-top {
width: 100%;
height: 70%;
-moz-user-select: none;
box-sizing: border-box;
position: relative;
}
#position {
width: 4%;
height: 6.11979%;
background-color: #FF503C;
border: 3px solid #90EE90;
box-shadow: 0px 0px 35px #87CEEB;
position: absolute;
border-radius: 50%;
transform: scaleY(0.75);
left: 85%;
top: 24%;
}
Here is a working Fiddle
I would use SVG instead, simple code and fully responsive:
svg {
display: block;
width: 100%;
}
circle {
stroke: white;
stroke-width: 3;
fill: red;
}
<svg viewBox="0 0 604 568">
<image x="0" y="0" width="586" height="604" xlink:href="http://i60.tinypic.com/2enrntu.jpg"/>
<circle cx="400" cy="190" r="20"/>
</svg>

Apple Like Javascript Slider

I need a slider like this one
http://itunes.apple.com/us/app/sparrow/id417250177?mt=12 (on Screenshots)
http://storymatters.com/showcase/there-is-an-app-for-that#slideshowWrap
Ideas?
That's just a custom scroll bar that works on webkit browsers: http://css-tricks.com/examples/WebKitScrollbars/ Here's an example
html {
overflow: auto;
}
body {
position: absolute;
top: 20px;
left: 20px;
bottom: 20px;
right: 20px;
padding: 30px;
overflow-y: scroll;
overflow-x: hidden;
}
/* Let's get this party started */
::-webkit-scrollbar {
width: 12px;
}
/* Track */
::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
-webkit-border-radius: 10px;
border-radius: 10px;
}
/* Handle */
::-webkit-scrollbar-thumb {
-webkit-border-radius: 10px;
border-radius: 10px;
background: rgba(255,0,0,0.8);
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5);
}
::-webkit-scrollbar-thumb:window-inactive {
background: rgba(255,0,0,0.4);
}
IE has a way to style scrollbars too, not as customizable though...
body {
scrollbar-arrow-color:#ffffff;
scrollbar-base-color: #ffffff;
scrollbar-dark-shadow-color:#ffffff;
scrollbar-track-color:#ffffff;
scrollbar-face-color:#ffffff;
scrollbar-shadow-color:#ffffff;
scrollbar-highlight-color:#ffffff;
scrollbar-3d-light-color:#ffffff;
}
So, if you want this to work across browsers, you're out of luck. The only way to do it is to write your own custom html for a scroll bar with the divs set to overflow: hidden

Categories

Resources