DEV Community

Discussion on: CSS Only Modal using target

Collapse
 
deathshadow60 profile image
deathshadow60 • Edited

Visibility leaves it in place, and prevents you being able to have a fade transition. Instead of visibility:hidden try position:absolute; left:-100vw; as you can then use transition delays to make it fade in/out.

I'd also suggest using selectors instead of blindly throwing classes at everything. The MYTH that "classes for everything" saves render time or other such nonsense is the realm of fantasy not fact. Even if big names like Google say otherwise in ignorance.

Likewise combining like attributes in selectors can help greatly reduce your code bloat, and using absolute positioning on the inner elements can work wonders for behavioral issues like a fade-in / fade-out transition.

It's why that translateY of yours doesn't seem to actually be doing anything... is that supposed to slide in from the top? Because it isn't.

Also remember that px is inaccessible trash that could lead to broken layouts for non-standard font-metric users like myself. (where my laptop and workstation are set to "large / 120dpi / 8514 / 125% / win7+ medium / pick a name already" and my media center is set to 32px thanks to the 4k display) 99.99% of the time you see a width in pixels, or padding in pixels, or font-size in pixels, you're looking at broken inaccessible methodology. It's called EM, use 'em! Much less the use of REM inside a pixel container... no... just ... no.

Hence I'd gut the markup down to:

<div id="greeting" class="modal">
    <a href="#"></a>
    <div>
        <h3>This is a modal</h3>
        <p>This is the modals content.</p>
  </div>
<!-- #greeting.modal --></div>

and then use CSS more along these lines:

/* assumes everything is set to box-sizing:border-box; */

.modal,
.modal > a {
    position:fixed;
    top:0;
    width:100%;
    height:100%;
}


.modal {
    left:-100vw;
    padding:0 2em;
    opacity:0;
    transition:left 0s 0.5s, opacity 0.5s;
    display:flex;
    justify-content:center;
    align-items:center;
    background:rgba(0,0,0,0.2);
}

.modal:target {
    left:0;
    opacity:1;
    transition:left 0s, opacity 0.5s;
}

.modal > a {
    position:absolute;
    left:0;
}

.modal > div {
    position:relative; /* depth sort over anchor */
    top:-50vh;
    width:100%;
    max-width:32em;
    padding:1em;
    background:#FFF;
    border-radius:0.5em;
    transition:top 0.5s;
}

.modal:target > div {
    top:0;
}

Have a look at my own older articles on this, where I use both the :target technique for a modal, and the input:checked technique for mobile menus.

cutcodedown.com/tutorial/modalDialogs
cutcodedown.com/tutorial/mobileMenu

I actually need to update both of those as I've been refining how I use them the past year and a half.

I've been using both methods for both effects interchangeably due to how sometimes you really do want to trigger them one way or the other. The INPUT approach is nice because it doesn't fill up the browser history. I often further enhance with this scripting:

var
    closeAnchors = document.querySelectorAll('.modal > a');

for (var i = 0, a; a = closeAnchors[i]; i++)
    a.addEvenListener('click', anchorBack, false);

function anchorBack(e) {
    e.preventDefault();
    window.history.back();
}

So that you don't fill up the browser history by hitting back. The advantage being you get the bells and whistles of scripted behavior, but it still works when scripting is blocked, disabled, or otherwise unavailable.

If you use the input:checked + div technique for your modals, it leaves the option to use :target for single-page that behaves as multiple pages, which is often handy when creating references. I made a x86 reference for my retrocomputing projects doing precisely that. The scripting is minimal to nonexistent on the page, even though the "pages" of said site are just one single HTML file.

x86.cutcodedown.com/

The only thing the scripting is really doing is locking out old browsers, and changing the window TITLE to match the first numbered heading when a section is navigated to via a link.

Fun stuff, it's absolutely amazing how much we can do faster, cleaner, simpler, and better without a lick of JavaScript.

Collapse
 
mandrewdarts profile image
M. Andrew Darts

So much knowledge in this comment, I really appreciate it!

I agree, I really like the checkbox approach as well. This was just a fun little hack I came across 😁

The transitions are subtle and quick. I can say they are working in Chrome based browsers.

I really appreciate you checking this out and providing feedback! I learned some things 🤘

Collapse
 
deathshadow60 profile image
deathshadow60 • Edited

The fade in transition "kind of" works here in Vivaldi (which is Blink/chromium based) but you have no fade-out animation at all -- because visibility cannot transition. Poof, it's gone.

Neither visibility or display:none are great choices when you want animations. It sucks bad, but that's just how it is.

Your TranslateY didn't seem to do anything I could see in any browser I tested (chromium, vivialdi, edge, firefox) hence why I made a more... exaggerated version with relative positioning that should be more apparent something is happening.

Same issue bit me when I was first starting to try to use these techniques for animations. The key is you're declaring a half second animation -- which is NOT a "quick" transition by any definition -- but you're not getting anywhere near that in the result... and the use of visibility is the cause.

Thread Thread
 
mandrewdarts profile image
M. Andrew Darts

"not working at all" to "kind of" I'll take it.

You are correct, .5s is not a quick transition. What I meant is the curve of the transition is quick.

I also agree that visibility and display are not properties you should be using for CSS animations, I was pretty surprised when it worked with visibility. I imagine it is a browser compatibility issue.

We are getting in the weeds a bit, this was just to show the target technique.

Thread Thread
 
deathshadow60 profile image
deathshadow60 • Edited

We are getting in the weeds a bit, this was just to show the target technique.

... and a very powerful technique it is, hence my giving it a big thumbs up and taking the time to expand upon it. We need to spread the word about these types of things so people can stop throwing JavaScript at things in a way that breaks accessibility.

There's so much we can do without JS now, and things that never should have been scripting's job in the first place that people still just blindly dive for JS to accomplish "the hard way".

Hell, there are still people calling themselves "experts" or "professionals" who will use JavaScript instead of :hover because they don't know enough HTML, CSS, or JS to even be building pages.

See half-witted incompetent trash like jQuery's "$(whatever).fade()". NOT JAVASCRIPT's JOB!

Avoiding using scripting in a broken way, or limiting scripting to enhancing a page instead of being the only means of providing functionality is SO important right now, what with the precedent set in the Domino's case that laws like the US ADA or UK EQA / DDA no longer just applying to medical/utilities/government/banking websites. It's also why things like letting react do render client-side is a walking talking /FAIL/ at development.

We NEED to get the word out that techniques like :target and :checked are how it should be done -- in as cleanly and gracefully degrading a manner as possible -- if for no other reason than for site owners to avoid getting dragged into court.

Thread Thread
 
mandrewdarts profile image
M. Andrew Darts

Yes! I really appreciate the conversation 😁