I'm making my own dropdown with CSS. You hover on it, then some options appear below it, you pick one and that's it. If there are too many options to fit there is a scroll bar. You can see the whole thing here: JSFiddle
let testData = [
"qwertyuiop",
"asdfghjkl",
"zxcvbnm",
"axdxfcbhdhvhv",
"äöäööäöääöää",
"zoinkszoinks",
"brrrrrrrrrr",
"gygygygyasdasda",
];
getTestStuff();
function getTestStuff() {
let content = document.getElementById("content");
let text = document.getElementById("text");
for (let group of testData) {
let div = document.createElement("div");
div.innerHTML = group;
div.addEventListener("click", function() {
text.innerHTML = group; // update button text
}, false);
content.appendChild(div);
}
}
let dropdown = document.getElementById("dropdown");
let arrow = document.getElementById("arrow");
let content = document.getElementById("content");
dropdown.addEventListener("mouseenter", function () {
arrow.className = "open";
content.classList.add("open");
}, false);
dropdown.addEventListener("mouseleave", function () {
arrow.className = "closed";
content.classList.remove("open");
}, false);
.dropdown-wrapper {
height: 40px;
float: left;
margin: 0px 5px;
}
.dropdown-wrapper, .dropdown-content {
width: 300px;
}
.dropdown-wrapper .header {
width: 100%;
height: 100%;
margin: 0;
background-color: #f1f1f1;
text-align: center;
border-radius: 5px;
font-size: 16px;
border: 1px solid grey;
display: table;
}
.dropdown-wrapper .header span {
text-align: center;
vertical-align: middle;
display: table-cell;
width: 100%;
}
.dropdown-wrapper .header div span {
font-size: 20px;
}
.dropdown-wrapper .header div {
margin-left: -40px;
width: 40px;
height: 40px;
float: right;
text-align: center;
display: table;
position: absolute;
}
.dropdown-content {
display: none;
float: none;
max-height: 300px;
overflow-x: hidden;
overflow-y: scroll;
position: absolute;
font-size: 16px;
background-color: #f1f1f1;
min-width: 0px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
margin-right: auto;
text-align: center;
}
.dropdown-content div {
color: black;
float: none;
padding: 12px 16px;
text-decoration: none;
display: block;
margin-right: -15px;
}
.dropdown-content div:hover {
background-color: #ddd;
}
.dropdown {
height: 100%;
width: 100%;
}
.dropdown:hover .dropdown-content {
display: block;
}
#arrow.open {
-webkit-animation-name: openArrowAnimation;
-webkit-animation-duration: 0.5s;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease;
-webkit-animation-fill-mode: forwards;
}
#arrow.closed {
-webkit-animation-name: closeArrowAnimation;
-webkit-animation-duration: 0.5s;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease;
-webkit-animation-fill-mode: forwards;
}
#-webkit-keyframes openArrowAnimation {
from {
-webkit-transform: rotate(0deg);
}
to {
-webkit-transform: rotate(180deg);
}
}
#-webkit-keyframes closeArrowAnimation {
from {
-webkit-transform: rotate(180deg);
}
to {
-webkit-transform: rotate(0deg);
}
}
#content.open {
-webkit-animation-name: openDropdownAnimation;
-webkit-animation-duration: 0.5s;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease;
-webkit-animation-fill-mode: forwards;
}
#-webkit-keyframes openDropdownAnimation {
from {
max-height: 0px;
}
to {
max-height: 300px;
}
}
<div class="dropdown-wrapper">
<div class="dropdown" id="dropdown">
<div class="header">
<span id="text">Test Thing</span>
<div id="arrow"><span>^</span></div>
</div>
<div id="content" class="dropdown-content">
</div>
</div>
</div>
The Problem:
The scrollbar appears during my animation. Which is not a problem, if it is going to stay, but when the content fits, it disappears again.
When the scroll bar is not there, the space that the scrollbar would take, does not have the right background color, when i hover over the option. Making a very ugly gap.
I know about overflow: auto; but i still use overflow: scroll; with margin-right: -16px; on the children, because my scrollbar moves the children and i only have that scrollbar sometimes.
I need some kind of CSS conditional hack to set overflow to hidden if we don't need it or use JS to change the margin-right but trying to check the parent height after adding the kids gave me this:
content.height: undefined
content.style.height: empty string
So i'm very lost with this.
I got it working with this trick on the children:
margin-right: calc(100% - 300px);
And setting the parent overflow to auto
This works because here 100% is the elements full width. Without a scroll bar, 100% is 300px, so margin is set to 0. With a scroll bar, 100% is around 290px so margin is set to around -10, so the text stays centered.
As #CBroe pointed out, i couldn't get the height of my element, or the children because it had display: none so to get around that:
let content = document.getElementById("content");
content.style.display = "block";
let height = content.offsetHeight;
content.style.display = "";
It's amazing something this dumb works so well. Now i can hide the scrollbar when i don't need it and fix the offset, that the scrollbar creates, when i do need it:
if (height < 300) {
content.style.overflowY = "hidden";
} else {
content.style.overflowY = "scroll";
for (let kid of content.children) {
kid.style.marginRight = "-16px";
}
}
This solution has the added bonus, that it works well with my animation. A problem that the CSS only solution couldn't solve.
Related
I am trying to create a tooltip for whatever that needs it on my website, e.g. a button, text, etc. So far I have something like this:
https://jsfiddle.net/f06q3cLg/
.content {
display: grid;
width: 100vw;
height: 100vh;
place-content: center;
}
.content .parent {
border: 1px red solid;
padding: 10px;
position: relative;
}
.content .parent:hover .tooltip-wrapper {
animation: 0.1s fadeInTooltip;
animation-fill-mode: forwards;
animation-delay: 0.4s;
}
.content .parent:hover:before {
animation: 0.1s fadeInTooltip;
animation-fill-mode: forwards;
animation-delay: 0.4s;
}
.content .parent:active .tooltip-wrapper {
animation: 0.05s fadeOutTooltip;
animation-fill-mode: forwards;
}
.content .parent:active:before {
animation: 0.05s fadeOutTooltip;
animation-fill-mode: forwards;
}
.content .parent:before {
content: "";
display: block;
width: 0;
height: 0;
position: absolute;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
left: 50%;
transform: translateX(-50%);
opacity: 0;
}
.content .parent .tooltip-wrapper {
position: absolute;
display: grid;
left: 0;
width: 300px;
height: 100%;
opacity: 0;
pointer-events: none;
}
.content .parent .tooltip-wrapper.bottom {
top: calc(100% + 8px);
}
.content .parent .tooltip-wrapper .tooltip {
max-width: 300px;
width: fit-content;
padding: 8px;
position: absolute;
display: inline-block;
background: blue;
border-radius: 5px;
padding: 8px;
color: white;
font-size: 11px;
box-shadow: 0px 3px 3px rgba(0, 0, 0, 0.2);
line-height: 1.3;
text-align: left;
}
/* Keyframes */
#keyframes fadeInTooltip {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes fadeOutTooltip {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
<div class="content">
<div class="parent">
Hover me
<div class="tooltip-wrapper">
<span class="tooltip">This is my tooltip</span>
</div>
</div>
</div>
As such, it works somewhat fine. My issue is that I would like the tooltip to disappear when I click the button. Now it vanishes, and then comes back with a 0.4s delay as the hover effect actually has. Ideally the tooltip should disappear as long as my mouse is still on the button, but when I remove it and re-enters the button, then the tooltip should re-appear.
I'm not sure if this is even achievable with pure CSS, but any JS would also do.
The problem is that :active is only applied as long as the mouse is down.
mdn: :active:
The :active CSS pseudo-class represents an element (such as a button) that is being activated by the user. When using a mouse, "activation" typically starts when the user presses down the primary mouse button.
What you could do (if you want to stay CSS only) is to use tabindex="0" on the <div class="parent"> and :focus instead of :active. But you need to verify that using tabindex="0" here won't hurt usability.
Ideally the tooltip should disappear as long as my mouse is still on the button, but when I remove it and re-enters the button, then the tooltip should re-appear.
That won't work with :focus either. I'm pretty sure that this behavior can only be achieved with JS. If it is possible with CSS only it likely would be a pretty hacky solution.
But from the perspective of a user, this seems to be counterintuitive that the tooltip won't appear after clicked.
A JavaScript solution that does what you want could look like this.
It is a simplified version of the tooltip to only show the relevant parts.
Every element having a tooltip has an attribute data-has-tooltip.
// event delegation for all mouse down event:
// this ensures that the code also works for elements that have been added to the DOM after that script was executed.
document.addEventListener('mousedown', (evt) => {
// check if the mousedown happened in an element with a tooltip
const element = evt.target.closest('[data-has-tooltip]');
if (element) {
// if the user already clicked on the element ignore the click
if (!element.classList.contains('active')) {
// add the active class to the element so that hover won't show the toolip
element.classList.add('active');
function removeActiveOnLeave() {
// remove the active class
element.classList.remove('active');
// remove the mouseleave event listener again
element.removeEventListener('mouseleave', removeActiveOnLeave)
}
// add an event listener for mouseleave to remove the active class
element.addEventListener('mouseleave', removeActiveOnLeave)
}
}
});
.parent {
display: inline-block;
border: 1px solid red;
padding: 0.5rem;
margin: 0.5rem;
}
.tooltip-wrapper {
display: none;
}
.parent:hover .tooltip-wrapper {
display: block;
}
.parent.active:hover .tooltip-wrapper {
display: none;
}
<div class="content">
<div class="parent" data-has-tooltip>
Hover me A
<div class="tooltip-wrapper">
<span class="tooltip">This is my tooltip A </span>
</div>
</div>
</div>
<div class="content">
<div class="parent" data-has-tooltip>
Hover me B
<div class="tooltip-wrapper">
<span class="tooltip">This is my tooltip B</span>
</div>
</div>
</div>
HTML
<div class="content">
<div class="parent" onClick="myFunction()">
Hover me
<div class="tooltip-wrapper">
<span class="tooltip" id="tooltip">This is mytooltip</span>
</div>
</div>
</div>
Javascript
function myFunction(){
var tooltip=document.getElementById("tooltip");
if (tooltip.style.display=="none") {
document.getElementById("tooltip").style.display="block";
} else {
document.getElementById("tooltip").style.display="none";
}
}
Manipulating 'display' property.
const parent = document.querySelector('.parent');
const toolTip = document.querySelector('.tooltip');
parent.addEventListener('click', () => {
if(toolTip.style.display !== 'none') {
toolTip.style.display = 'none';
}else {
toolTip.style.display = 'grid';
}
});
A solution using jQuery 3.4.1:
$(".parent").click(function () {
$(".tooltip-wrapper").css("display", "none");
});
The only downfall with that solution is once you click and re-hover in the same session, the SCSS :hover doesn't work properly.
No need to stress, just add the following if you want that functionality:
$(".parent").hover(function () {
$(".tooltip-wrapper").css("display", "block");
});
Try it out in the attached snippet:
$(".parent").click(function () {
$(".tooltip-wrapper").css("display", "none");
});
$(".parent").hover(function () {
$(".tooltip-wrapper").css("display", "block");
});
.content {
display: grid;
width: 100vw;
height: 100vh;
place-content: center;
}
.content .parent {
border: 1px red solid;
padding: 10px;
position: relative;
}
.content .parent:hover .tooltip-wrapper {
animation: 0.1s fadeInTooltip;
animation-fill-mode: forwards;
animation-delay: 0.4s;
}
.content .parent:hover:before {
animation: 0.1s fadeInTooltip;
animation-fill-mode: forwards;
animation-delay: 0.4s;
}
.content .parent:active .tooltip-wrapper {
animation: 0.05s fadeOutTooltip;
animation-fill-mode: forwards;
}
.content .parent:active:before {
animation: 0.05s fadeOutTooltip;
animation-fill-mode: forwards;
}
.content .parent:before {
content: "";
display: block;
width: 0;
height: 0;
position: absolute;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
left: 50%;
transform: translateX(-50%);
opacity: 0;
}
.content .parent .tooltip-wrapper {
position: absolute;
display: grid;
left: 0;
width: 300px;
height: 100%;
opacity: 0;
pointer-events: none;
}
.content .parent .tooltip-wrapper.bottom {
top: calc(100% + 8px);
}
.content .parent .tooltip-wrapper .tooltip {
max-width: 300px;
width: fit-content;
padding: 8px;
position: absolute;
display: inline-block;
background: blue;
border-radius: 5px;
padding: 8px;
color: white;
font-size: 11px;
box-shadow: 0px 3px 3px rgba(0, 0, 0, 0.2);
line-height: 1.3;
text-align: left;
}
/* Keyframes */
#keyframes fadeInTooltip {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes fadeOutTooltip {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="content">
<div class="parent">
Hover me
<div class="tooltip-wrapper">
<span class="tooltip">This is my tooltip</span>
</div>
</div>
</div>
OR, you can see it working in this Fiddle. with your initial
SCSS.
You can uncomment the second function to see the hover working again after clicking.
So here is a simple fiddle (http://jsfiddle.net/t1xywroc/2/) I created to show you the animation I'm trying to replicate (from this website: https://paperpillar.com/).
I'm still fairly new to Javascript/Jquery and have only been doing HTML and CSS for a couple months.
The problem about my animation is that (as far I know) there is no transition from an absolute position to a fixed position, which I believe causes that small jump, right after triggering the animation (or transition if you will). The second problem is, that the content of the ::before element can't be transitioned either. How can I fix these things using jQuery?
I tried to get it work by using mostly CSS but I keep coming across new problems. I guess it's inevitable to use JavaScript, which is what I need help with. I'd really appreciate it.
Note: not a native speaker.
HTML
<div class="section">
<div class="button"></div>
</div>
CSS
.section {
height: 2000px;
width: auto;
}
.button {
position: absolute;
transform: translateX(50%);
right: 50%;
display: inline-block;
color: white;
line-height: 60px;
height: 60px;
width: auto;
padding-left: 25px;
padding-right: 25px;
background-color: blue;
border-radius: 25px;
vertical-align: middle;
top: 15rem;
}
.button::before{
content: 'Button Text';
}
.floating {
padding-left: 0px;
padding-right: 0px;
position: fixed;
right: 15px;
top: calc(100vh - 120px);
transform: none;
height: 80px;
width: 80px;
transition: all 1.5s ease-in-out;
background-color: red !important;
border: none;
border-radius: 50%;
justify-content: center;
text-align: center;
}
.floating::before{
content:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24px' height='24px' fill='white'><path d='M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z' /></svg>");
}
JS
$(document).ready(function() {
$(window).on('scroll', function() {
if ($(window).width() <= 768) {
var scrollTop = $(this).scrollTop();
$('.button').each(function() {
var topDistance = $(this).offset().top;
if ((topDistance - 30) < scrollTop) {
$(this).addClass('floating');
// Haven't put much thought into this part yet
} else if ((topDistance - 30) >= scrollTop){
}
});
}
});
});
A couple of problems have been highlighted in the question: the 'jump' when the transition moves between absolute and fixed and the fact that pseudo elements' content can not be transitioned.
To get round the absolute to fixed jump problem we can set the button to fixed as soon as the transition is to start and then transition. This is possible by introducing CSS animations rather than transitions.
To appear to transition between content we use before pseudo element to hold the initial text (as in the code given) and introduce an after pseudo element that holds the svg. To give the appearance of transitioning between the two we animate opacity.
Note: in the website which is to be emulated the button initially has a white background over the page's white background. This means the change in shape as the initial button fades away is less obvious. With a contrasting blue background the change in shape is much more obvious. That may or may not be the effect required.
Here's a snippet with animations instead of transitions and moving to fixed immediately the animation starts.
$(document).ready(function() {
$(window).on('scroll', function() {
if ($(window).width() <= 2500) {
var scrollTop = $(this).scrollTop();
$('.button').each(function() {
var topDistance = $(this).offset().top;
if ((topDistance - 30) < scrollTop) {
$(this).addClass('floating');
} else if ((topDistance - 100) >= scrollTop){
}
});
}
});
});
.section {
height: 2000px;
width: auto;
position: relative;
}
.button, .button::before, .button::after {
animation-duration: 1.5s;
animation-iteration-count: 1;
animation-fill-mode: forwards;
animation-timing-function: ease-in-out;
position: absolute;
}
.button {
transform: translateX(50%);
right: 50%;
line-height: 60px;
height: 60px;
width: auto;
color: transparent; /* do this to ensure the button has dimensions so it can be clicked */
display: inline-block;
vertical-align: middle;
top: 15rem;
}
.button.floating {
position: fixed;
top: 30px;
animation-name: floatdown;
}
.button::before {
content: 'Button\00a0 Text';
opacity: 1;
color: white;
line-height: 60px;
height: 60px;
width: auto;
padding-left: 25px;
padding-right: 25px;
background-color: blue;
border-radius: 25px;
}
.button::after {
content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24px' height='24px' fill='white'><path d='M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z' /></svg>");
opacity: 0;
padding-left: 0px;
padding-right: 0px;
height: 80px;
width: 80px;
margin-left: -50%;
background-color: red;
border: none;
border-radius: 50%;
justify-content: center;
text-align: center;
}
div.button.floating::before {
animation-name: fadeout;
}
div.button.floating::after {
animation-name: fadein;
}
#keyframes fadeout {
100% {
opacity: 0;
}
}
#keyframes fadein {
100% {
opacity: 1;
}
}
#keyframes floatdown {
100% {
top: calc(100vh - 120px);
right: 95px; /* 80+15px */
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="section">
<div class="button">Button text</div>
</div>
Note also that if you want the downarrow to fill the circle more you could put it as a background-image with size contain rather than as content.
Ultimately, for each click of a button, I want to display an element that contains new content. In other words...
You read content contained within a parent container
To see the next item click the button
When the button is clicked, the old content shifts downward. The new content flows down from the top of the container. It pauses in order to read the new content.
To get new content, press the button again.
I'm unclear as to how to accomplish this, and if it's even possible with a CSS Animation. With what I have posted, it just takes both elements and translates them down the vertical axis at once. How can this be refactored so that one element pauses and displays it's content using just vanilla JavaScript?
var div1 = document.querySelector(".first");
var div2 = document.querySelector(".second");
var button = document.querySelector("button");
var divs = [div1, div2];
button.addEventListener("click", function(event) {
event.preventDefault();
for (var i = divs.length - 1; i > -1; i--) {
var div = divs[i];
div.classList.remove("down_shift");
void div.offsetWidth;
div.classList.add("down_shift");
}
});
body {
background: #222;
}
section {
width: 50vw;
height: 300px;
border: 5px solid red;
margin: 50px auto;
overflow: hidden;
}
.first, .second {
width: inherit;
height: 300px;
background: red;
transform: translateY(-300px);
}
.second {
background: pink;
}
h1 {
margin: 0;
padding-top: 50px;
text-align: center;
}
.down_shift {
animation: down 1s ease-out;
}
#keyframes down{
from {
transform: translateY(0);
}
to {
transform: translateY(300px);
}
}
<section>
<div class="first"><h1>1</h1></div>
<div class="second"><h1>2</h1></div>
</section>
<button type="button">Click</button>
You can add a wrapper to the elements, and animate the wrapper
var wrapper = document.querySelector(".wrapper");
var button = document.querySelector("button");
button.addEventListener("click", function(event) {
event.preventDefault();
wrapper.style.transform = 'translateY(-300px)'
});
body {
background: #222;
}
section {
width: 50vw;
height: 300px;
border: 5px solid red;
margin: 50px auto;
overflow: hidden;
}
.first, .second {
width: inherit;
height: 300px;
background: red;
/* transform: translateY(-300px); */
}
.second {
background: pink;
}
.wrapper {
transition: all 1s ease-out;
}
h1 {
margin: 0;
padding-top: 50px;
text-align: center;
}
.down_shift {
animation: down 1s ease-out;
}
#keyframes down{
from {
transform: translateY(0);
}
to {
transform: translateY(300px);
}
}
<section>
<div class="wrapper">
<div class="first"><h1>1</h1></div>
<div class="second"><h1>2</h1></div>
</div>
</section>
<button type="button">Click</button>
I just got off support with ActiveCampaign and they said they couldn't provide me with code examples on how to add their modal pop-up forms to be triggered by wordpress buttons.
I found a few resources online but they are all slightly different than the functionality I'm looking for.
I already added the ActiveCampaign plugin to my wordpress site and there are two options of embedding the form within the site.
shortcode "[activeCampaign formId=1]" or
<script src="https://exampledomain.com/f/embed.php?id=1" type="text/javascript" charset="utf-8"></script>
I'm currently using the divi theme, and the buttons have sections for CSS ID's and CSS Classes.
so to summarize, I would like to be able to click a button and have the activecampaign modal form popup.
If you could show me how I can add code to the button and my site to trigger the modal popup that'd be amazing.
Let me know if you have any other information.
Thanks!
Sugesstion:
This involves DOM manipulation. create a css class called active which should be set to the form container to show. Here's an example:
var formToggle = document.getElementById("form-toggler");
var formContainer = document.querySelector(".form-container");
formToggle.addEventListener('click', function(){
// When you click the button, first check if the form is open
// so that you know if you should close or open
if(formContainer.classList.contains("active")){
// Form is currently open, because it has active as one of it's classes
// so remove active to hide it.
formContainer.classList.remove("active");
}else{
// Form is currently closed, because it does not have active as one of it's classes
// so add active to show it.
formContainer.classList.add("active");
}
});
.form-container{
width: 100%;
height: 100%;
min-height: 200px;
background-color: rgba(0,0,0,0.2);
display: none;
}
/* When form has active class, set display to block */
.form-container.active{
display: block !important;
}
<div class="form-container">
<!-- your Form Here -->
<h1>Yey, form is active!!</h1>
</div>
<button id="form-toggler">OpenForm<button>
This is just at the basic level of approaching your scenario. So you've got to work on your css to make your Modal cover the entire window and add a close button on it in case someone decides to close it.
Hey this should work for you also. Bear in mind there is some extra code you probably wont need all of it such as the animations but I will leave these in as they make the modal look a little slicker. You won't need bootstrap or any additional libraries for this code.
HTML:
<a id="gdx-lighbox-modal-unique-1" data-hover="true" type="button" class="gdx-lightbox-tooltip-open-modal lightbox-link gdx-lightbox-button" data-open="gdx-lighbox-modal-1">
Click Here
</a>
<div class="gdx-modal" id="gdx-lighbox-modal-1" data-animation="slideInOutLeft">
<div class="gdx-modal-dialog">
<header class="gdx-modal-header">
<a class="gdx-close-modal" aria-label="close modal" data-close="">✕</a>
</header>
<section class="gdx-modal-content">
//Form would go here instead of the image (image just an example)
<img src="https://gdxdesigns.com/wp-content/uploads/2020/11/little-frog.jpg"> </section>
<footer class="gdx-modal-footer"> <h3 class="gdx-modal-image-title"></h3></footer>
</div>
</div>
CSS:
/* RESET RULES
–––––––––––––––––––––––––––––––––––––––––––––––––– */
:root {
--lightgray: #efefef;
--blue: steelblue;
--white: #fff;
--black: rgba(0, 0, 0, 0.8);
--bounceEasing: cubic-bezier(0.51, 0.92, 0.24, 1.15);
}
* {
padding: 0;
margin: 0;
}
.gdx-body {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
font: 16px/1.5 sans-serif;
}
.lightbox-link, a.lightbox-link {
cursor: pointer;
margin-left: 2.5%;
}
.gdx-lightbox-tooltip-open-modal img {
width: 20px;
height: 20px;
}
.gdx-lightbox-button {
padding: 10px 20px;
background: #000;
padding: 10px 20px;
font-weight: normal;
border: 2px solid #000;
color: #94c93b;
}
.gdx-lightbox-button:hover {
background: #FFF;
color: #000;
}
/* MODAL
–––––––––––––––––––––––––––––––––––––––––––––––––– */
.gdx-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
background: var(--black);
cursor: pointer;
visibility: hidden;
opacity: 0;
transition: all 0.35s ease-in;
z-index: 9999 !important;
}
.gdx-modal.is-visible {
visibility: visible;
opacity: 1;
}
.gdx-modal-dialog {
position: relative;
max-width: 100vw;
max-height: 100vh;
border-radius: 5px;
background: var(--white);
overflow: auto;
cursor: default;
margin-top: 5%;
}
.gdx-modal-dialog > * {
padding: 1rem;
}
.gdx-modal-header,
.gdx-modal-footer {
background: #FFF;
}
.gdx-modal-header .gdx-close-modal {
font-size: 1.5rem;
}
.gdx-modal-header a {
font-size: 2em;
}
.gdx-modal-content {
text-align: center;
}
.gdx-modal-content img {
margin: 0 !important;
}
.gdx-close-modal {
float: right;
cursor: pointer;
}
.gdx-modal p + p {
margin-top: 1rem;
}
.gdx-modal-image-title {
text-align: center;
font-size: 1em;
margin: 0;
}
/* ANIMATIONS
–––––––––––––––––––––––––––––––––––––––––––––––––– */
[data-animation] .gdx-modal-dialog {
opacity: 0;
transition: all 0.5s var(--bounceEasing);
}
[data-animation].is-visible .gdx-modal-dialog {
opacity: 1;
transition-delay: 0.2s;
}
[data-animation="slideInOutDown"] .gdx-modal-dialog {
transform: translateY(100%);
}
[data-animation="slideInOutTop"] .gdx-modal-dialog {
transform: translateY(-100%);
}
[data-animation="slideInOutLeft"] .gdx-modal-dialog {
transform: translateX(-100%);
}
[data-animation="slideInOutRight"] .gdx-modal-dialog {
transform: translateX(100%);
}
[data-animation="zoomInOut"] .gdx-modal-dialog {
transform: scale(0.2);
}
[data-animation="rotateInOutDown"] .gdx-modal-dialog {
transform-origin: top left;
transform: rotate(-1turn);
}
[data-animation="mixInAnimations"].is-visible .gdx-modal-dialog {
animation: mixInAnimations 2s 0.2s linear forwards;
}
[data-animation="slideInOutDown"].is-visible .gdx-modal-dialog,
[data-animation="slideInOutTop"].is-visible .gdx-modal-dialog,
[data-animation="slideInOutLeft"].is-visible .gdx-modal-dialog,
[data-animation="slideInOutRight"].is-visible .gdx-modal-dialog,
[data-animation="zoomInOut"].is-visible .gdx-modal-dialog,
[data-animation="rotateInOutDown"].is-visible .gdx-modal-dialog {
transform: none;
}
#keyframes mixInAnimations {
0% {
transform: translateX(-100%);
}
10% {
transform: translateX(0);
}
20% {
transform: rotate(20deg);
}
30% {
transform: rotate(-20deg);
}
40% {
transform: rotate(15deg);
}
50% {
transform: rotate(-15deg);
}
60% {
transform: rotate(10deg);
}
70% {
transform: rotate(-10deg);
}
80% {
transform: rotate(5deg);
}
90% {
transform: rotate(-5deg);
}
100% {
transform: rotate(0deg);
}
}
/* Backend Instructions
–––––––––––––––––––––––––––––––––––––––––––––––––– */
.lightbox-instructions-heading {
font-size: 1.8em !important;
}
.lightbox-instructions strong {
font-size: 1.2em !important;
}
.gdx-lightbox-tooltip-open-modal img {
margin: -0.3em;
margin-left: 0.25em;
}
xmp {
white-space: normal;
}
.lightbox-tooltip-instructions-content xmp{
margin-bottom: 2em;
}
Javascript
const openEls = document.querySelectorAll("[data-open]");
const closeEls = document.querySelectorAll("[data-close]");
const isVisible = "is-visible";
for (const el of openEls) {
el.addEventListener("click", function() {
const modalId = this.dataset.open;
document.getElementById(modalId).classList.add(isVisible);
});
}
for (const el of closeEls) {
el.addEventListener("click", function() {
this.parentElement.parentElement.parentElement.classList.remove(isVisible);
});
}
document.addEventListener("click", e => {
if (e.target == document.querySelector(".gdx-modal.is-visible")) {
document.querySelector(".gdx-modal.is-visible").classList.remove(isVisible);
}
});
document.addEventListener("keyup", e => {
// if we press the ESC
if (e.key == "Escape" && document.querySelector(".gdx-modal.is-visible")) {
document.querySelector(".gdx-modal.is-visible").classList.remove(isVisible);
}
});
JSFiddle Example can be seen here.
If you want to download this as a Wordpress Plugin (free of course) you can do so here
If you want to see the a demo of the plugin in action with the button modal popup you see this here
I have this simple HTML DIV where the word "Loading" is in the middle.
I also have the JavaScript code to change the dots in the #waitDotDotDot element.
var dots = window.setInterval( function() {
var wait = document.getElementById("waitDotDotDot");
if ( wait.innerHTML.length > 5 )
wait.innerHTML = "";
else
wait.innerHTML += ".";
}, 300);
<div style="width: 90%; text-align:center; margin-right:auto; margin-left:auto; border: 1px solid black;">
<div style="margin-right:auto; margin-left:auto; width:90%;">
Loading <span id="waitDotDotDot">.</span>
</div>
</div>
This is working, but it keeps resizing the "Loading" text (pushing it to the left) when the numbers of dots is increasing. Is there a way to keep the "Loading" text in the same position (still center), but only the dots are resizing while it is increasing?
For this kind of effect, personally I'd forego the script to keep it simple and solve the issue at the same time.
.container {
border: green 1px dashed;
}
.dotme {
margin-left: calc(50% - 4rem);
transform: translateX(-50%);
display: inline;
font-size: 2rem;
border: red 1px dotted;
}
.dotme:after {
content: "\2026";
display: inline-block;
width: 0;
overflow: hidden;
vertical-align: bottom;
animation: dots steps(4,end) .75s infinite alternate;
}
#keyframes dots {
to { width: 3rem;}
}
<div class="container">
<aside class="dotme">Loading</aside>
</div>
I modified Chris W.'s post to achieve the desired result.
.divWrapper {
width: 100%;
text-align: center;
}
.loading {
font-size: 2rem;
display: inline-block;
}
.dots {
visibility: hidden;
position: relative;
}
.dots::before {
content: "\2026";
visibility: visible;
display: inline-block;
position: absolute;
width: 0;
overflow: hidden;
vertical-align: bottom;
animation: dots steps(4,end) 1s infinite forwards;
}
#keyframes dots {
to { width: 2.5rem;}
}
<div class="divWrapper">
<p class="loading">
Loading<span class="dots">…</span>
</p>
</div>