1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

Pure CSS Galley Carousel with Keypress?

Discussion in 'HTML & Website Design' started by 7643sfsag6, Dec 30, 2019.

  1. #1
    Hi I have a pure css carousel lightbox which is working fine.
    However, I would like to do three things:
    -when i press ESC it simulates clicking the close button;
    -when pressing left and right it simulates clicking the left/right button; and,
    -when i click off the image, the lightbox closes.
    Ideally it would be great if this can be done in pure css.

    Here is a fiddle: https://jsfiddle.net/postcolonialboy/Lxa2pgrw/3/

    (If not, willing to accept jquery :p)

    Here is what I have:

    <span class="feature_category active" id="A">
      <div class="feature_box_wrapper"><a href="#groys1">Link</a></div>
      <div class="feature_box_wrapper"><a href="#groys2">Link</a></div>
      <div class="feature_box_wrapper"><a href="#groys3">Link</a></div>
       <div class="feature_box_wrapper"><a href="#groys4">Link</a></div>
       <div class="feature_box_wrapper"><a href="#groys5">Link</a></div>
    </span>
    <div class="lightbox">
      <!-- Groys -->
      <div class="lightbox__slide" id="groys1">
        <a href="#_" class="btn btn--close"></a>
        <a href="#groys5" class="btn btn--left"></a>
        <a href="#groys2" class="btn btn--right"></a>
        <img src="https://picsum.photos/seed/picsum/800/450" alt="Screenshot of your site">
      </div>
      <div class="lightbox__slide" id="groys2">
        <a href="#_" class="btn btn--close"></a>
        <a href="#groys1" class="btn btn--left"></a>
        <a href="#groys3" class="btn btn--right"></a>
        <img src="https://picsum.photos/seed/picsum/800/450" alt="Screenshot of your site">
      </div>
      <div class="lightbox__slide" id="groys3">
        <a href="#_" class="btn btn--close"></a>
        <a href="#groys2" class="btn btn--left"></a>
        <a href="#groys4" class="btn btn--right"></a>
        <img src="https://picsum.photos/seed/picsum/800/450" alt="Screenshot of your site">
      </div>
      <div class="lightbox__slide" id="groys4">
        <a href="#_" class="btn btn--close"></a>
        <a href="#groys3" class="btn btn--left"></a>
        <a href="#groys5" class="btn btn--right"></a>
        <img src="https://picsum.photos/seed/picsum/800/450" alt="Screenshot of your site">
      </div>
      <div class="lightbox__slide" id="groys5">
        <a href="#_" class="btn btn--close"></a>
        <a href="#groys4" class="btn btn--left"></a>
        <a href="#groys1" class="btn btn--right"></a>
        <img src="https://picsum.photos/seed/picsum/800/450" alt="Screenshot of your site">
      </div>
      <div class="lightbox__bg"></div><!-- Close -->
    </div><!-- Close Lightbox -->
    HTML:




    .lightbox__slide img {
      position: absolute;
      z-index: 30;
      max-width: 90%;
      max-height: 80%;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      animation-name: hide;
      animation-duration: 0.5s;
      animation-iteration-count: 1;
      animation-direction: linear;
      animation-fill-mode: forwards;
    }
    .lightbox__slide:target .btn {
      display: block;
    }
    .lightbox__slide:target img {
      opacity: 0;
      animation-name: show;
      animation-duration: 0.5s;
      animation-iteration-count: 1;
      animation-direction: linear;
      animation-fill-mode: forwards;
    }
    .lightbox__slide:target~.lightbox__bg {
      position: relative;
      background: white;
      opacity: 0.6;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      z-index: 1;
    }
    @-webkit-keyframes show {
      0% {
        opacity: 0;
      }
      100% {
        opacity: 1;
      }
    }
    @-webkit-keyframes hide {
      0% {
        opacity: 1;
      }
      100% {
        opacity: 0;
      }
    }
    .btn {
      position: absolute;
      z-index: 20;
      display: none;
      transition: all 0.2s;
      width: 40px;
      height: 40px;
      margin: -20px 0 0 -20px;
      text-align: center;
      line-height: 40px;
      text-decoration: none;
      color: black;
    }
    .btn:hover {
      background: rgba(255, 255, 255, 0.8);
    }
    .btn--close {
      top: 40px;
      right: 20px;
    }
    .btn--close:after {
      content: '\2715';
    }
    .btn--left {
      top: 50%;
      left: 40px;
    }
    .btn--left:after {
      content: '⯇';
    }
    .btn--right {
      top: 50%;
      right: 20px;
    }
    .btn--right:after {
      content: '⯈';
    }
    Code (CSS):
     
    Solved! View solution.
    Last edited: Dec 30, 2019
    7643sfsag6, Dec 30, 2019 IP
  2. qwikad.com

    qwikad.com Illustrious Member Affiliate Manager

    Messages:
    7,151
    Likes Received:
    1,656
    Best Answers:
    29
    Trophy Points:
    475
    #2
    I'd suggest using pure javascript (non-jQuery) carousel sliders. They work perfect in most browsers and on mobile devices. css only sliders will not work as you expect them to on ipads and cell phones. Don't create a headache for yourself, go for a javascript slider.

    PS @deathshadow has pure javascript sliders. Maybe he can point you to the right link on his site.
     
    Last edited: Dec 30, 2019
    qwikad.com, Dec 30, 2019 IP
  3. 7643sfsag6

    7643sfsag6 Member

    Messages:
    58
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    43
    #3
    ok thanks for the advice, i remember @deathshadow grilling me a number of times for using jquery/JS when CSS does a perfectly good job!
     
    7643sfsag6, Dec 30, 2019 IP
  4. #4
    Really the moment you want keyboard interaction, you're looking at adding scripting. Whilst CSS can save you a LOT of the grunt work in terms of show/hide, there are some things you do still need scripting to handle.

    Now that said, first thing I'd suggest is fixing your semantics. You have a LIST of links in no particular order, why is that in a SPAN with invalid "div for nothing" inside it instead of UL/LI? Since you don't have nesting of DIV inside each slide, why do they need a class. If all the anchors are getting the same class, why do any of them need classes?

    So first, let's skim off the dross.

    
    <ul class="lightbox_menu">
    	<li><a href="#groys1">Link</a></li>
    	<li><a href="#groys2">Link</a></li>
    	<li><a href="#groys3">Link</a></li>
    	<li><a href="#groys4">Link</a></li>
    	<li><a href="#groys5">Link</a></li>
    </ul>
    
    <div class="lightboxes">
    
      <div id="groys1">
        <a href="#" class="close"></a>
        <a href="#groys5" class="prev"></a>
        <a href="#groys2" class="next"></a>
        <img
    			src="https://picsum.photos/seed/picsum/800/450"
    			alt="Screenshot of your site"
    		>
      </div>
      
      <div id="groys2">
        <a href="#" class="close"></a>
        <a href="#groys1" class="prev"></a>
        <a href="#groys3" class="next"></a>
        <img
    			src="https://picsum.photos/seed/picsum/800/450"
    			alt="Screenshot of your site"
    		>
      </div>
      
      <div id="groys3">
        <a href="#" class="close"></a>
        <a href="#groys2" class="prev"></a>
        <a href="#groys4" class="next"></a>
        <img
    			src="https://picsum.photos/seed/picsum/800/450"
    			alt="Screenshot of your site"
    		>
      </div>
      
      <div id="groys4">
        <a href="#" class="close"></a>
        <a href="#groys3" class="prev"></a>
        <a href="#groys5" class="next"></a>
        <img
    			src="https://picsum.photos/seed/picsum/800/450"
    			alt="Screenshot of your site"
    		>
      </div>
      
      <div id="groys5">
        <a href="#" class="close"></a>
        <a href="#groys4" class="prev"></a>
        <a href="#groys1" class="next"></a>
        <img
    			src="https://picsum.photos/seed/picsum/800/450"
    			alt="Screenshot of your site"
    		>
      </div>
      
    <!-- .lightBoxes --></div>
    Code (markup):
    Then for the CSS something more along the lines of (taking some artistic liberties)

    
    .lightboxes > div,
    .lightboxes .close {
    	top:0;
    	width:100%;
    	height:100%;
    }
    
    .lightboxes > div {
    	box-sizing:border-box;
    	display:flex;
      align-items:center;
      justify-content:center;
      position:fixed;
    	left:-100vw;
    	padding:3em;
    	opacity:0;
    	transition:left 0s 0.5s, opacity 0.5s;
    	background:rgba(0,128,255,0.7);
    	box-shadow:inset 0 0 255px rgba(0,0,64,0.7);
    }
    
    .lightboxes > div:target {
    	left:0;
    	opacity:1;
    	transition:left 0s, opacity 0.5s;
    }
    
    .lightboxes a {
    	text-decoration:none;
    	color:#000;
    	transition:color 0.5s;
    }
    
    .lightboxes a:focus,
    .lightboxes a:hover {
    	color:#0FF;
    }
    
    .lightboxes a:before {
    	position:absolute;
    	font-size:2em;
    	line-height:1em;
    }
    
    .lightboxes .close {
    	position:absolute;
    	left:0;
    }
    
    .lightboxes .close:before {
    	position:absolute;
    	top:0.25em;
    	right:0.25em;
    	content:"\1F5D9";
    }
    
    .lightboxes .prev:before,
    .lightboxes .next:before {
    	width:1.5em;
    	top:50%;
    	text-align:center;
    	margin-top:-0.5em;
    }
    
    .lightboxes .prev:before {
    	left:0;
    	content:"\25C0";
    }
    
    .lightboxes .next:before {
    	right:0;
    	content:"\25BA";
    }
    
    .lightboxes img {
    	max-width:100%;
    	max-height:100%;
    	box-shadow:0 0 3em rgba(0,0,128,0.7);
    }
    
    Code (markup):
    Now the scripting doesn't have to get too complex. We just need to intercept keystrokes at the document level, then look at the hash to see what's focused. If the focused element's parent is a .lightboxes, check the keystroke and grab the appropriate child anchor and perform .click() on it. Naturally checks for if said elements exist and resolve should be done across the entire process.

    
    (function(d, w) {
    	// remember, arrows don't trigger keypress :(
    	d.addEventListener('keydown', lightBoxCheck, false);
    	function lightBoxCheck(e) {
    		var hash = w.location.hash ? w.location.hash.substr(1) : '';
    		if (!hash) return;
    		var
    			target = d.getElementById(hash),
    			method;
    		if (
    			target &&
    			target.parentNode.className == 'lightboxes'
    		) {
    			switch(e.keyCode) {
    				case 27:
    					method = '.close';
    					break;
    				case 37:
    					method = '.prev';
    					break;
    				case 39:
    					method = '.next';
    					break;
    				default:
    					// short circuit out
    					return;
    			}
    			if (target = target.querySelector(method)) {
    				target.click();
    				e.preventDefault();
    			}
    		}
    	}
    })(document, window);
    Code (markup):
    ... and of course it's in a SIF (aka IIFE) to isolate its scope so other scripts don't interfere. Also notice that if we intercept the keystroke we cancel the event preventing further propagation, but allow other keystrokes to continue about their business so other scripts if present (or browser functionality) can still work.

    Live demo:

    https://cutcodedown.com/for_others/7643sfsag6/lightbox/

    Not significantly far off from what you wrote, and the scripting is built to ENHANCE the page instead of supplanting functionality. That's the billion dollar trick is that scripting off it's still usable for touch, mouse, and even conventional tab style keyboard navigation -- but the tiny bit of scripting enhances it with keyboard input.
     
    deathshadow, Jan 1, 2020 IP
  5. 7643sfsag6

    7643sfsag6 Member

    Messages:
    58
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    43
    #5
    Wow!

    much cleaner and does everything perfectly even in touch! thanks @deathshadow
     
    7643sfsag6, Jan 1, 2020 IP
  6. ketting00

    ketting00 Well-Known Member

    Messages:
    772
    Likes Received:
    27
    Best Answers:
    3
    Trophy Points:
    128
    #6
    Nice little function, but why use the hash. This thing is supposed gonna be a bit dynamic.
     
    ketting00, Jan 3, 2020 IP
  7. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #7
    It is dynamic because the hash and :target are how the markup works without the scripting. It's the fastest and easiest way to get the current slide without having the script seize full control of how it works.

    What would you suggest instead / where would you grab the current slide from?
     
    deathshadow, Jan 3, 2020 IP
  8. ketting00

    ketting00 Well-Known Member

    Messages:
    772
    Likes Received:
    27
    Best Answers:
    3
    Trophy Points:
    128
    #8
    As you say so then. I use the getAttribute. Just curious.
     
    ketting00, Jan 3, 2020 IP
  9. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #9
    GetAttribute on what? you need an element to get the attribute OF first.

    The slideshow itself works WITHOUT JavaScript by using hashes... the current hash and the :target is the only indication of what slide is current...

    So how would "getAttribute" get you the currently :target element?
     
    deathshadow, Jan 3, 2020 IP
  10. ketting00

    ketting00 Well-Known Member

    Messages:
    772
    Likes Received:
    27
    Best Answers:
    3
    Trophy Points:
    128
    #10
    Hmm! Mine isn't working without scripting. I'm targeting the images IDs or images names.
     
    ketting00, Jan 3, 2020 IP
  11. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #11
    Define "isn't working" -- as in keyboard (which is what the scripting provides) or the normal mouse interface?

    Also what do names have to do with anything? Also define what you mean by "yours".
     
    deathshadow, Jan 3, 2020 IP
  12. ketting00

    ketting00 Well-Known Member

    Messages:
    772
    Likes Received:
    27
    Best Answers:
    3
    Trophy Points:
    128
    #12
    OK, I don't want to be grinded on this. I use getAttribute to get the image identification out of the link like you do with the hash and
    substr and just curious about this. By using substr, it has to fall into a specific length.

    If it worked, it just works.
     
    ketting00, Jan 3, 2020 IP
  13. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #13
    From what? Could you provide a code example of what you mean as I AM interested in other ways of doing things, and I genuinely have ZERO cluie what you're talking about.

    ... and using substr all I'm doing is removing the first character, which is always a # so, just what are you even on about?
     
    deathshadow, Jan 3, 2020 IP
  14. LewisH95

    LewisH95 Greenhorn

    Messages:
    118
    Likes Received:
    8
    Best Answers:
    0
    Trophy Points:
    23
    #14
    .lightbox__slide img {
    position: absolute;
    z-index: 30;
    max-width: 90%;
    max-height: 80%;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    animation-name: hide;
    animation-duration: 0.5s;
    animation-iteration-count: 1;
    animation-direction: linear;
    animation-fill-mode: forwards;
    }

    .lightbox__slide:target .btn {
    display: block;
    }

    .lightbox__slide:target img {
    opacity: 0;
    animation-name: show;
    animation-duration: 0.5s;
    animation-iteration-count: 1;
    animation-direction: linear;
    animation-fill-mode: forwards;
    }

    .lightbox__slide:target~.lightbox__bg {
    position: relative;
    background: white;
    opacity: 0.6;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 1;
    }

    @-webkit-keyframes show {
    0% {
    opacity: 0;
    }

    100% {
    opacity: 1;
    }
    }

    @-webkit-keyframes hide {
    0% {
    opacity: 1;
    }

    100% {
    opacity: 0;
    }
    }

    .btn {
    position: absolute;
    z-index: 20;
    display: none;
    transition: all 0.2s;
    width: 40px;
    height: 40px;
    margin: -20px 0 0 -20px;
    text-align: center;
    line-height: 40px;
    text-decoration: none;
    color: black;
    }

    .btn:hover {
    background: rgba(255, 255, 255, 0.8);
    }

    .btn--close {
    top: 40px;
    right: 20px;
    }

    .btn--close:after {
    content: '\2715';
    }

    .btn--left {
    top: 50%;
    left: 40px;
    }

    .btn--left:after {
    content: '⯇';
    }

    .btn--right {
    top: 50%;
    right: 20px;
    }

    .btn--right:after {
    content: '⯈';
    }
     
    LewisH95, May 8, 2020 IP