So I've been trying to get a transition working properly in firefox, This is what I have at the moment:
index.html:
<button type="button" id="pushButton">Push Me!</button>
<div id="loginBackground" class="login-background">
<div id="loginBox" class="login-box-inactive">
</div>
</div>
global_style.css:
.login-background {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
background: rgba(0, 0, 0, 0.4);
}
.login-box-inactive, .login-box-active {
display: flex;
flex-flow: column nowrap;
min-width: 150px;
min-height: 150px;
background: #fff;
margin: auto;
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.4);
}
.login-box-active {
min-width: 350px;
min-height: 350px;
transition: width 2s, height 2s, ease-in-out, 0.5s;
}
finally, login.js:
"use strict";
var pushButton = document.getElementById("pushButton");
var loginBackground = document.getElementById("loginBackground");
var loginBox = document.getElementById("loginBox");
pushButton.onclick = function() {
loginBackground.style.display = "flex";
loginBox.className = "login-box-active";
}
window.onclick = function(event) {
if(event.target == loginBackground) {
loginBackground.style.display = "none";
loginBox.className = "login-box-inactive";
}
}
AFAIK, pretty much every modern browser to date has standardised the transition tag so why is it that firefox is ignoring the transition tag entirely?
Thanks!
EDIT:
So I now have the following within my CSS file:
transition-property: all;
transition-duration: 1s;
transition-timing-function: ease-in-out;
Chrome plays well and displays this as should. Firefox still continues to ignore them. I even prefixed -moz- on them and it still ignored them.
EDIT 2:
I would like the following to happen once the button is pressed:
1) User presses Press Me! button.
2) loginBackground then overlays any content below (imagine the button is not the only content on page), rendering none of it clickable.
3) User will then have a choice of filling form out within loginBox or clicking a closeButton or loginBackground, both of which have the following outcome:
3.1) Upon user clicking either closeButton or loginBackground the loginBox and loginBackground disappears, leaving content underneath usable.
The problem is both of these browsers handle the display property kind of differently. The execution of your transition depends on the display property of the loginBackground which is "display:none" initially. The box that is changing the dimension is a child of this division. Now, the interesting thing that is happening is:
Firefox is removing the child of the parent which has display:none set
Here's what firefox's mdn doc on display says:
In addition to the many different display box types, the value none lets you turn off the display of an element; when you use none, all descendant elements also have their display turned off. The document is rendered as though the element doesn't exist in the document tree.
That's why when you are toggling display value on firefox the transition's don't occur since it's kind of removed and reinserted; essentially making it have no previous value to start of the transition from.
If you apply the "login-box-active" class with a slight delay, everything starts working as expected
"use strict";
var pushButton = document.getElementById("pushButton");
var loginBackground = document.getElementById("loginBackground");
var loginBox = document.getElementById("loginBox");
pushButton.onclick = function() {
loginBackground.style.display = "flex";
setTimeout(function() {
loginBox.className = "login-box-active";
}, 400)
}
window.onclick = function(event) {
if(event.target == loginBackground) {
loginBackground.style.display = "none";
loginBox.className = "login-box-inactive";
}
}
.login-background {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
background: rgba(0, 0, 0, 0.4);
}
.login-box-inactive, .login-box-active {
display: flex;
flex-flow: column nowrap;
min-width: 150px;
min-height: 150px;
background: #fff;
margin: auto;
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.4);
}
.login-box-active {
min-width: 350px;
min-height: 350px;
transition: width 2s, height 2s, ease-in-out 0.5s;
}
<button type="button" id="pushButton">Push Me!</button>
<div id="loginBackground" class="login-background">
<div id="loginBox" class="login-box-inactive">
</div>
</div>
In the curious case of Chrome, it kind of does not remove the child of "display:none". That's why the transition works as usual on it.
Although, I would suggest to use simple opacity to achieve such effect instead of playing with display. Something, like this:
"use strict";
var pushButton = document.getElementById("pushButton");
var loginBackground = document.getElementById("loginBackground");
var loginBox = document.getElementById("loginBox");
pushButton.onclick = function() {
loginBackground.style.opacity = "1";
loginBox.className = "login-box-active";
}
window.onclick = function(event) {
if(event.target == loginBackground) {
loginBox.className = "login-box-inactive";
loginBackground.style.opacity = "0";
}
}
.login-background {
opacity: 0;
position: fixed;
display: flex;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
background: rgba(0, 0, 0, 0.4);
transition: opacity 2s;
}
.login-box-inactive, .login-box-active {
display: flex;
flex-flow: column nowrap;
background: #fff;
width: 150px;
height: 150px;
margin: auto;
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.4);
transition: width 2s, height 2s, ease-in-out 0.5s;
}
.login-box-active {
width: 350px;
height: 350px;
}
<button type="button" id="pushButton">Push Me!</button>
<div id="loginBackground" class="login-background">
<div id="loginBox" class="login-box-inactive">
</div>
</div>
transition: width 2s, height 2s, ease-in-out, 0.5s;
This line seems to be incorrect.
Try to remove last value and move timing function to a separate property.
Related
In this stackblitz, I am not able to add animation while closing, I tried it using transform, but it didnt seem to work
HTML
Blocker is used to covering the full screen in a half-transparent mode in mobile devices
const sidebar = document.querySelector('.sidebar');
sidebar.querySelector('.blocker').onclick = hide;
function show() { // swipe right
sidebar.classList.add('visible');
document.body.style.overflow = 'hidden';
}
function hide() { // by blocker click, swipe left, or url change
sidebar.classList.remove('visible');
document.body.style.overflow = '';
}
function toggle() {
sidebar.classList.contains('visible') ? hide() : show();
}
.sidebar {
/* it's a mobile sidebar, blocker and content */
position: fixed;
top: 0;
left: 0;
width: 100vw;
/* to cover the whole screen */
height: 100vh;
padding: 0;
/* to override the default padding */
background: rgba(0, 0, 0, .5);
/* half transparent background */
display: none;
z-index: 99999;
/* to be on top of any other elements */
}
.sidebar.visible {
display: block;
}
/*cover the whole screen and to detect user click on background */
.sidebar .blocker {
position: absolute;
width: 100%;
height: 100%;
}
/* user content */
.sidebar .content {
position: absolute;
top: 0;
left: 0;
background: #FFF;
height: 100%;
width: 250px;
left: -50%;
/* will be animated to left: 0, by animation */
animation: slide 0.5s forwards;
}
#keyframes slide {
100% {
left: 0;
}
}
<div class="sidebar">
<div class="blocker"></div>
<div class="content">
Sidebar Content
</div>
</div>
With the above code, you can have a working sidebar.
Check the working code from stackblitz
https://allenhwkim.medium.com/mobile-friendly-sidebar-in-few-minutes-7817b5c5239f
https://stackblitz.com/edit/medium-sidebar-1-eevvax?file=style.css,index.js
You can't animate between display:block (when .sidebar has .visible applied to it) and display:none (when .visible is removed from .sidebar).
display:none turns off the display of an element so that it has no effect on layout (the document is rendered as though the element did not exist). All descendant elements (i.e. .blocker and .content) also have their display turned off.
The reason you get an animation upon adding .visible is that .sidebar now "exists" and so .sidebar-content also exists and as such animates. As soon as you remove .visible, .sidebar ceases to exist again and so it and its descendants disappear instantaneously.
You are along the right lines using transforms but you need to remove display:none as the method for hiding the sidebar. Something like the below is a good starting point. You may need to change some values to get it looking exactly as you wish. I have added a working codepen to show the result.
.sidebar {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
padding: 0;
background: rgba(0, 0, 0, .5);
z-index: 99999;
transform: translateX(-100%); // new property - will move the element off the left hand side of the screen
transition: transform .5s ease-in-out; // new property - will make the sidebar slide in in a similar manner to your animation
}
.sidebar.visible {
transform: translateX(0); // new property - makes sidebar sit in its natural position (i.e. taking up the whole viewport)
}
.sidebar .blocker {
position: absolute;
width: 100%;
height: 100%;
}
.sidebar .content {
position: absolute;
top: 0;
left: 0;
background: #FFF;
height: 100%;
width: 250px;
}
I have a problem trying to keep some help text associated with a "?" image positioned appropriately horizontally. Although it works as I would like most of the time, when the "?" moves too close to the left of the screen (either because the "?" is close to the left in the first place, or a width reduction wraps it there), the help gets chopped off
I like it to appear in a box 15rem wide, as high as it needs to be, positioned above and extending to the left of the "?", and to be visible on either a hover or click. That works fine.
What I can't figure out is how to move the help to the right by just as much as is necessary to avoid it extending off the left-hand side of the screen whenever that is necessary.
I have added another class (not shown) to those tips that I know are near the left, that extends them right instead of left. However it's not a good solution, relying on me finding them, and not coping with window resizing very well.
What I have so far is:
HTML And CSS:
.tooltip {
position: relative;
}
.tooltip > img {
vertical-align: middle;
margin-left: 0.5rem;
height: 20px;
}
.tooltip .tooltiptext {
visibility: hidden;
background-color: #555;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 0.5rem;
position: absolute;
z-index: 1;
bottom: 125%;
width: 15rem;
right: 0;
margin-right: 1rem;
opacity: 0;
transition: opacity 1s;
}
.tooltip:hover .tooltiptext, .tooltip:active .tooltiptext {
visibility: visible;
opacity: 1;
}
<div>
<input type="text" name=xx size="40" placeholder="xxxxxx">
<span class="tooltip">
<img src="static/help.png" alt="help">
<span class="tooltiptext">Some help text for this.</span>
</span>
</div>
I'm guessing the key is dynamically determining the position of tooltiptext and adjusting left/right accordingly but I'm at a loss to know how to do that. I'm limited to CSS & JS (i.e. not JQuery).
Any help gratefully accepted.
Thanks, Chris
Here is not quite well solution, but it gives you some useful thoughts.
let tooltips = document.querySelectorAll('.tooltip');
[].forEach.call(tooltips, (el) => {
el.addEventListener('mouseover', showTooltip, this);
});
function setDefaultPosition(element) {
element.style.top = 'auto';
element.style.right = 'auto';
element.style.bottom = 'auto';
element.style.left = 'auto';
}
function showTooltip(event) {
let tooltip = event.currentTarget.querySelector('.tooltiptext')
setDefaultPosition(tooltip);
let {top:bodyTop, right:bodyRight, bottom:bodyBottom, left:bodyLeft} = document.body.getBoundingClientRect();
let {top:tooltipTop, right:tooltipRight, bottom:tooltipBottom, left:tooltipLeft} = tooltip.getBoundingClientRect();
if (bodyTop < tooltipTop) {
tooltip.style.top = '100%';
}
if (bodyBottom < tooltipBottom){
tooltip.style.bottom = '100%';
}
if (bodyRight < tooltipRight) {
tooltip.style.right = '100%';
}
if (bodyLeft > tooltipLeft){
tooltip.style.left = '100%';
}
};
Example here
I think there is more than on CSS solution. It could be done with flexbox:
https://codepen.io/anon/pen/ZJpQWE
.wrapper {
margin-top: 10rem;
width: 100%; /* adjust the with to your needs */
display: flex;
position: relative;
}
.some-input {
width: 100%;
}
.tooltip > img {
vertical-align: middle;
height: 20px;
}
.tooltip .tooltiptext {
visibility: hidden;
background-color: #555;
color: #fff;
text-align: center;
position: absolute;
z-index: 1;
bottom: 125%;
width: 100%;
right: 0;
opacity: 0;
transition: opacity 1s;
padding: .5rem;
box-sizing: border-box;
border-radius: 6px;
}
.tooltip:hover .tooltiptext, .tooltip:active .tooltiptext {
visibility: visible;
opacity: 1;
}
I have a navigation div with a height of 0px, when I click a hamburger icon I want a class with 250px height to be added. I'm using an event listener to detect the click which is tested with an alert and working. ToggleClass() is then being used to add the class.
In the developer console I can see the class ebing added however the height of the div isn't changing and you can also see that the height rule isn't being detected/displayed in the console, even with a strikethrough.
Here is an image of the relevent info from dev console: https://gyazo.com/900f858cbfc41e9e8bfe00eb9fd8f1cb
styles.css:
#responsiveNav {
position: absolute;
right: 0;
width: 200px;
height: 0px;
text-align: center;
background-color: rgba(28, 28, 27, 0.8);
color: #009641;
margin-top: 100px;
overflow: hidden;
z-index: 1500;
transition: all 0.8s ease;
}
.mobNavHeight {
height: 250px;
}
JS:
$(document).ready(function () {
var hamburgerBtn = document.getElementById("hamburgerBtn");
//DISPLAY MOBILE NAVIGATION ON HAMBURGER CLICK
function displayMobNav() {
alert("working");
$('#responsiveNav').toggleClass("mobNavHeight");
}
//EVENT LISTENERS
hamburgerBtn.addEventListener("click", displayMobNav);
}); //Doc Ready
It's a CSS specificity issue. An id has a higher specificity than a class. Use this in your CSS instead.
#responsiveNav.mobNavHeight {
height: 250px;
}
But if I were you, I wouldn't use an id to target an element via CSS in the first place. Only use the id to target in javascript, but in CSS just use a class like .responsiveNav, move all of the #responsiveNav styles to that, then use .mobNavHeight to overwrite it. Like this.
<nav id="responsiveNav" class="responsiveNav">nav</nav>
.responsiveNav {
position: absolute;
right: 0;
width: 200px;
height: 0px;
text-align: center;
background-color: rgba(28, 28, 27, 0.8);
color: #009641;
margin-top: 100px;
overflow: hidden;
z-index: 1500;
transition: all 0.8s ease;
}
.mobNavHeight {
height: 250px;
}
You can see example here: http://codepen.io/dimsemenov/pen/gbadPv
Click on Share button and you'll see it blurs the image (and everything else).
I am observing this in inspector and I can't figure it out.
I have downloaded source code and it set a watch in photoswipe-ui-defaults.js in this last line:
_openWindowPopup = function(e) {
e = e || window.event;
var target = e.target || e.srcElement;
pswp.shout('shareLinkClick', e, target);
It never gets executed.
I have added other similar modal and I want to achieve same effect, but I can't figure out what is being done to achieve that blur.
Well, it would looks partly complicated that's why it isn't clear for the first look.
There all time rendered .pswp_share-modal with this css
Share Modal:
.pswp_share-modal {
display: block;
background: rgba(0,0,0,0.5);
width: 100%;
height: 100%;
top: 0;
left: 0;
padding: 10px;
position: absolute;
z-index: 1600;
opacity: 0;
-webkit-transition: opacity .25s ease-out;
transition: opacity .25s ease-out;
-webkit-backface-visibility: hidden;
will-change: opacity;
}
When you click to the "share" button somewhere in js .pswp__share-modal--fade-in class attaches to the same element with this css:
Modal with fade in effect:
.pswp__share-modal--fade-in {
opacity: 1
}
As you can see the general idea is to turn opacity to 100% when share modal is active. Blur effect is exist cause actual modal background has rgba(0,0,0,0.5);
What you have to do is add an extra div, make it full screen, and then add a background to the div. I have an example here (it looks ugly but you'll catch what I'm trying to say).
$(document).ready(function() {
$('#modal-btn').click(function(){
$('.modal').css("display","block");
});
$('.modal').click(function(){
$(this).css("display","none");
});
});
html, body {
background-color: #000;
color: #fff;
height: 100%;
width: 100%;
z-index: 1;
}
.modal {
background-color: #000;
background-color: rgba(0, 0, 0, 0.5);
display: none;
height: 100vh;
position: absolute;
top: 0;
left: 0;
width: 100vw;
z-index: 2;
}
.modal-content {
background-color: #aaa;
height: 50%;
margin: 10px auto;
text-align: center;
width: 50%;
z-index: 3;
}
<html>
<head></head>
<body>
<!-- Page content -->
<div>
The content that goes in the background.
<button id="modal-btn" class="btn">Open Modal</button>
</div>
<!-- Modal -->
<div class="modal">
<div class="modal-content">The Modal Content</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</body>
</html>
I am planning a two-tier fixed position navigation at the top of my design.
As the user scrolls down the page, I would like the navigation to slide up until the first tier is mostly hidden.
If the user then hovers over the navigation, the container should slide down revealing the first tier again.
This hover effect should not fire if the user is at the very top of the browser window.
Additionally, when the user scrolls back to the very top of the page, the full two-tier navigation should again be fully visible as it is on the initial load.
I'm having trouble chaining these events together using javascript and have had to resort to a combination of CSS3 transitions and jQuery addClass/removeClass calls.
Additionally, I can only get the whole mish-mash to fire once. So once the user has scrolled down and back up there is no more animation.
My current code is viewable at this fiddle
Hopefully this gives an idea of what I'm trying to do.
Can anyone help me bring this monstrosity to life?
Code is as follows:
HTML
<div id="nav_wrap">
<div id="nav_one">
<h2>Nav One</h2>
</div>
<div id="nav_two">
<h3>Nav Two</h3>
</div>
</div>
<p>blah blah blah etc...</p>
CSS
#nav_wrap {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 120px;
z-index: 100;
}
#nav_one,
#nav_two {
float: left;
width: 100%;
height: 48px;
background: #111;
}
#nav_two {
background: #1f4c6b;
height: 72px;
}
h2, h3 {
color: #fff;
}
#nav_wrap.fixed {
margin-top: -42px;
-webkit-transition: margin-top .5s ease-in-out;
box-shadow: 0 0 24px #111;
}
#nav_wrap.down {
margin-top: 0px;
-webkit-transition: margin-top .5s ease-in-out;
}
#nav_wrap.drop {
top: 42px;
-webkit-transition: top .5s ease-in-out;
}
#nav_wrap.up {
top: 0;
-webkit-transition: top .5s ease-in-out;
}
Javascript
var top = $('#nav_wrap').offset()
.top - parseFloat($('#nav_wrap')
.css('marginTop')
.replace(/auto/, 0));
$(window).scroll(function (event) {
var y = $(this).scrollTop();
if (y > top) {
$('#nav_wrap').addClass('fixed');
$("#nav_wrap").hover(
function () {
$(this).addClass('drop');
},
function () {
$(this).addClass('up');
}
);
} else if (y == 0) {
$('#nav_wrap').addClass('down');
}
});
You're overcomplicating your approach. All you actually need to do is toggle one class on scroll in your JavaScript. This CSS will do the rest.
Note: The code will need prefixes added for other browsers (-moz, -o, -ms) and I would look at improving the performance of the addClass part of the call in scroll as the event will be getting called a lot.
An example fiddle can be found here.
CSS
#nav_wrap {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 120px;
z-index: 100;
}
#nav_one,
#nav_two {
width: 100%;
height: 48px;
background: #111;
}
#nav_two {
background: #1f4c6b;
height: 72px;
}
h2, h3 {
color: #fff;
}
#nav_wrap{
-webkit-transition: margin-top .5s ease-in-out;
}
#nav_wrap.scroll {
margin-top: -42px;
box-shadow: 0 0 24px #111;
}
#nav_wrap.scroll:hover{
margin-top: 0px;
}
JS
$(window).scroll(function (event) {
var y = $(this).scrollTop();
if (y > 0) {
$('#nav_wrap').addClass('scroll');
}
else{
$('#nav_wrap').removeClass('scroll');
}
});