I'm trying to make a modal box with an animation when it appear and disappear.
I tried using css3 transition.
HTML
<div id="modal" class="modal">
<div id="modalcontent" class="modal-content" >
<div class="modal-header">
<span class="close" onclick="closeList()" >x</span>
<h2>Lista File</h2>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<span id="sendlistButt" class="send" onclick="sendList()" >salva</span>
</div>
</div>
CSS
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 5; /* Sit on top */
padding-top: 100px; /* Location of the box */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
.modal-content {
position: relative;
background-color: #fefefe;
margin: auto;
padding: 0;
border: 1px solid #444;
width: 650px;
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);
top: -300px;
opacity: 0;
-webkit-transition: top 5s, opacity 5s ; /* Safari */
transition: top 5s, opacity 5s ;
}
.animatetop {
top: 0;
opacity: 1;
}
JS
function close() {
document.getElementById("modal").style.display="none";
document.getElementById("modalcontent").classList.remove("animatetop");
}
function open() {
document.getElementById("modalcontent").classList.add("animatetop");
document.getElementById("modal").style.display="block";
}
This make the modal appear and disappear but without transition.
What am i doing wrong?
Any css transitions that run depend on the element being visible with display:block or similar.
By calling
document.getElementById("modal").style.display="none"; at the start of your close() function you instantly set the entire modal to be completely hidden, so the transition on the modalcontent has no effect.
Likewise in the open() function, the transition class is applied but the element is hidden by display:none so the transition does not run.
You should try to have the transition run, then after a delay set the modal to be hidden.
function close() {
document.getElementById("modalcontent").classList.remove("animatetop");
window.setTimeout(function(){
document.getElementById("modal").style.display="none"; //hide modal after 5s delay
}, 5000);
}
and for the open, set the modal visible first, then add the transition class:
function open() {
document.getElementById("modal").style.display="block";
document.getElementById("modalcontent").classList.add("animatetop");
}
Changing display property will not let browser do the animation. It works instantly. Even using transition: display will not help.
Related
I would like to make my modal contained in the container (the red area).
When I set position to relative, the modal opens from left to right whereas I want it to open from right to left
And the modal goes after the button when I want it to go over everything in the red area.
#container{ background-color:red; width: 100%; height: 300px }
.modal {
display: block;
position: absolute;
z-index: 99;
right: 0; top: 0;
width: 100%; height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.4);
animation: slide-in 1s linear 1;
}
#keyframes slide-in { 0% { width: 0; } 25% { width: 25%; } 50% { width: 50%; } 75% { width: 75%; } 100% { width: 100%; }
}
.modal-content { background-color: #fefefe; margin: 20px; padding: 20px; border: 1px solid #888;
}
<div id=container>
<button id="open-modal-btn">Open modal</button>
</br>
<div id="my-modal" class="modal">
<div class="modal-content">
<h2>title</h2>
<p>content</p>
</div>
</div>
</div>
UPDATE: Sorry I mis-read your original post. In any case, the technique below is still preferred; just swap values.
To get a from-left slide with your current code as it exists, change right to left in your modal class.
.modal {
/* Change right to left */
/* right: 0; */
left: 0;
}
However your slide-in technique is awkward. You're achieving a slide by growing the width of the modal, so semantically this is a "grow-in". You're lucky that your content is not warping, and that it happens to appear as a "slide-in". A more elegant way to actually slide-in would be to use transform: translate(0,0) on the modal.
Instead I'd do this, roughly:
Codepen link
.modal {
/* ... */
/* Gives motion to changed properties like transform */
transition: all 0.5s ease;
/* Default off-screen left */
transform: translate(-100%,0);
/* Default off-screen right */
/* transform: translate(100%,0); */
}
.modalOpened .modal {
/* Set back to zero (center of viewport) */
transform: translate(0,0);
}
In addition, in your modal open event (the button click) simply toggle a class modalOpened on the app container. No keyframes needed. Just a natural, and actual, slide-in.
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 am using David Walsh css flip effect: http://davidwalsh.name/css-flip
I have this working onClick with a JavaScript function called showCard(). See the codePen here:
https://codepen.io/Chris_Nielsen/pen/YaWmMe
When you first click the button, it animates correctly (opens from left to right). However, when you click the button again, it closes animates from right to left. The third time the button is clicked it opens again animates correctly (from left to right) again.
What I want to do is get this to re-open from left to right every time.
Can someone point out how I can make this work? I have worked on this for 2 hours and am stumped.
The Code:
function showCard() {
document.querySelector("#errorMessage").classList.toggle("flip");
}
body {
background: #575955;
color: white;
}
.error-box {
width: 380px;
height: 110px;
background: #fff;
border: solid 1px #B71C1C;
border-radius: 9px;
font-family: 'Raleway', sans-serif;
font-size: 1.6rem;
color: #B71C1C;
text-align: center;
padding: 30px;
}
/* entire container, keeps perspective */
.flip-container {
perspective: 1000px;
}
/* flip the pane when hovered */
.flip-container.flip .flipper {
visibility: visible;
transform: rotateY(90deg);
/* transform: rotateY(90deg); */
}
.flip-container, .front, .back {
width: 320px;
height: 480px;
}
/* flip speed goes here */
.flipper {
transition: .35s;
transform-style: preserve-3d;
position: relative;
}
/* hide back of pane during swap */
.front, .back {
backface-visibility: hidden;
position: absolute;
top: 0;
left: 0;
}
/* front pane, placed above back */
.front {
z-index: 2;
/* for firefox 31 */
transform: rotateY(-90deg);
}
/* back, initially hidden pane */
.back {
transform: rotateY(180deg);
}
<h1>Click the button below to see the <br>animated alert.</h1>
<div class="flip-container" id="errorMessage" >
<div class="flipper">
<!-- text here will rotate -->
<div class="front">
<!-- front content -->
<br><br><br>
<div class="error-box">
Email address or password <br>
Incorrect. <br>
Please Try Again.
</div>
</div>
<div class="back">
<!-- back content -->
</div>
</div>
</div>
<input type="button" value="Show card" onClick="showCard();">
I think it will help to explain a little bit of what is going on here in the code you have now. In short, you've created an action based on a CSS class that fires on a click. The important part to note here is that this action is based on the addition of a class.
visually...your html looks something like this (using alternate elements here for simplification).
<element class="class1">some text</element>
then when you click the button, this changes the HTML markup to look something like this...
<element class="class1 class2">some text</element>
which in turn, hits your css sheet which now fires off the action that you want...in your case...flipping the card.
So the reason why your card is flipping the direction you want on first click, and then flipping back the opposite direction on your second click, is because you are simply adding a class that says, "turn me 90 degrees", and then on the 2nd click, removing that same class which tells your CSS to basically "undo" that move.
I'm not sure what the best approach will be if you want to continue to use what David Walsh wrote, plug and play, because it wasn't really designed to do what you're looking for. One approach may be to add a second class that completes another 90degree rotation on click 2, and then hide the element while you remove the two classes that undo your rotations.
Update 1 - Created a working version here off of your codepen here... https://codepen.io/SEAjamieD/pen/bvggOw?editors=0110
Probably not ideal to add and remove classes so quickly like that but it works. You might think about moving the animations into a keyframe. Hope this helps!
Okay, I finally got this working so that every time the button is clicked the card opens from right to left. It took a combination of #Jamie D's idea above about removing and re-adding classes with the idea of using a jQuery function with a timer that automatically reclicks the button.
Solution can be seen on codepen here:
https://codepen.io/Chris_Nielsen/pen/LdWPPG
Here is the solution code.
var card = document.querySelector("#errorMessage");
var container = document.querySelector('.flip-container');
var isOpen = false;
function showCard() {
if (!isOpen) {
container.style.visibility = "visible";
card.classList.add("flip");
document.querySelector(".flipper").classList.toggle("flip");
isOpen = true;
} else if (isOpen) {
card.classList.toggle("flip");
isOpen = false;
clickAgain();
}
}
function clickAgain(){
setTimeout(function() {
$(document).ready(function(){
$("#b1").click()
});
}, 350);
}
body {
background: #575955;
color: white;
}
.error-box {
width: 380px;
height: 110px;
background: #fff;
border: solid 1px #B71C1C;
border-radius: 9px;
font-family: 'Raleway', sans-serif;
font-size: 1.6rem;
color: #B71C1C;
text-align: center;
padding: 30px;
}
/* Hide the flip container to start */
.flip-container {
perspective: 1000px;
visibility: hidden;
}
.flip-container.flip .flipper {
transform: rotateY(90deg);
transition: 0.35s;
}
.flip-container, .front, .back {
width: 320px;
height: 200px;
}
/* flip speed goes here */
.flipper {
transition: 0s;
transform-style: preserve-3d;
position: relative;
}
/* hide back of pane during swap */
.front, .back {
backface-visibility: hidden;
position: absolute;
top: 0;
left: 0;
}
/* front pane, placed above back */
.front {
z-index: 2;
/* for firefox 31 */
transform: rotateY(-90deg);
}
/* back, initially hidden pane */
.back {
transform: rotateY(90deg);
/* transform: rotateY(180deg); */
}
<h1>Click the button below to see the <br>animated alert.</h1>
<div class="flip-container" id="errorMessage" >
<div class="flipper">
<!-- text here will rotate -->
<div class="front">
<!-- front content -->
<div class="error-box">
Email address or password <br>
Incorrect. <br>
Please Try Again.
</div>
</div>
<div class="back">
<!-- back content -->
</div>
</div>
</div>
<input type="button" id="b1" value="Show card" onClick="showCard();">
It seems overtime I add a image to my modal, it gets off centered from the user page.
When I say off centered, I mean the modal will be more down while leaving space on top.
I made a JS fiddle so you can see for yourself (resize your browser to 1230x650 if you can't see it)
https://jsfiddle.net/2whfsnqe/
Image of the problem:
How can I make my modal center correctly when a image is added?
Js fiddle code:
<button onclick='noImage()'>
Open modal without image
</button>
<button onclick='withImage()'>
Open modal with image
</button>
<div id="myModal" class="modal">
<div id='modal-content' class="modal-content">
<div id='modal-header' class="modal-header">
<span id='close' class="close">×</span>
<h2 id='modal-title'><!--- modal-title to set data !---></h2>
</div>
<div class="modal-body" id="modal-body"><!--- modal-body to set data !---></div>
<div class="modal-footer" id="modal-footer"><!--- modal-footer to set data !---></div>
</div>
</div>
<script>
var modal = document.getElementById('myModal');
var span = document.getElementsByClassName("close")[0];
function noImage(){
setModalTitle("HELLO!");
setModalBody("<p>This modal has no image - and is centered fine.</p>");
openModal();
}
function withImage(){
setModalTitle("HELLO!");
setModalBody("<p>This modal has a image, and isn't centered right :(</p><p>See how it goes off the page if you resize your browser to be smaller while leaving space on top?</p><img src='https://chart.googleapis.com/chart?chs=250x250&cht=qr&chl=3G58sN2JVX3tLBBDKfuUZ9q3fmG3nZ53iY '>");
openModal();
}
function openModal(){
span.onclick = function() {
closeModal();
}
window.onclick = function(event) {
if (event.target === modal) {
closeModal();
}
}
modal.style.display = "block";
}
function closeModal(){
modal.style.display = "none";
setModalBody("");
setModalTitle("");
}
function setModalTitle(text){
document.getElementById("modal-title").innerHTML = text;
}
function setModalBody(html){
document.getElementById("modal-body").innerHTML = html;
}
</script>
/* modals */
/* The Modal (background) */
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
padding-top: 10%;
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
/* Modal Content */
.modal-content {
position: relative;
background-color: #FFFFFF;
margin: auto;
padding: 0;
width: 80%;
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);
-webkit-animation-name: animatetop;
-webkit-animation-duration: 0.4s;
animation-name: animatetop;
animation-duration: 0.4s;
text-align: center;
}
/* Add Animation */
#-webkit-keyframes animatetop {
from {top:-300px; opacity:0}
to {top:0; opacity:1}
}
#keyframes animatetop {
from {top:-300px; opacity:0}
to {top:0; opacity:1}
}
/* The Close Button */
.close {
color: #000;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
cursor: pointer;
opacity: 0.7;
}
.modal-header {
padding: 2px 16px;
background-color: #FFFFFF;;
color: black;
}
.modal-body {padding: 2px 16px;}
.modal-footer {
padding: 2px 16px;
background-color: #FFFFFF;
color: black;
}
The modal container has a padding-top value of 10%, and since padding percentages are based on the width of the container (see here), it's expanding along with the width.
To fix it, you could either change the padding to an absolute value, or use flexbox to align it in the centre of the window.
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>