css slideshow carousel

¿Implementar una presentación de diapositivas/carrusel solo para CSS con los botones siguiente y anterior?



slideshow carousel (1)

un ejemplo de trabajo

http://jsfiddle.net/q4d9m/2/

ACTUALIZACIÓN: Parece que hay un error con Firefox 32 (Mac) que significa que los puntos suspensivos no se mostrarán en las máscaras SVG, esto lleva a que la reflexión falle ... y no me refiero a lo que es Chrome 37.0.2062.120 (Mac) haciendo si desplaza el mouse sobre cualquiera de las imágenes en el ejemplo implementado al pie de esta respuesta.

- 18 de septiembre de 2014 .


explicando el principio básico

Las diapositivas se construyen a partir de dos partes principales, una parte visual y una parte interactiva. La parte interactiva se mantiene prácticamente estática y la parte visual está animada. Después de jugar mucho extendí la estructura HTML inicial (ver más arriba) para incorporar algunos envoltorios adicionales alrededor del contenido de la diapositiva. Esto permite las partes interactivas y visuales separadas, y también una flexibilidad adicional para otras habilidades útiles, como el centrado vertical y los reflejos.

<ul class="css-slider"> <li class="slide" tabindex="1" id="l1"> <span class="slide-outer"> <span class="slide-inner"> <span class="slide-gfx" id="s1"> <img src="photos/a.jpg" /> </span> </span> </span> </li> <li class="slide" tabindex="1" id="l2"> <span class="slide-outer"> <span class="slide-inner"> <span class="slide-gfx" id="s2"> <img src="photos/b.jpg" /> </span> </span> </span> </li> ... </ul>

Ahora, para que cualquier sistema se comporte como una presentación de diapositivas, debe tener alguna forma de identificar la diapositiva actual o enfocada. En este caso estoy confiando en :focus para manejar esta distinción. Es posible que haya notado la adición de tabindex=“1” arriba, esto es para que la pseudo-clase :focus se aplique a elementos inesperados como <li> - esto fue requerido principalmente para los navegadores basados ​​en webkit, pero puede ayudar a otros agentes también.

En pocas palabras, todas las diapositivas se apilan una encima de la otra, la diapositiva enfocada actual se centra en la ventana gráfica y, dado el z-index más alto, la diapositiva anterior a la diapositiva enfocada se traslada de la pantalla a la izquierda y la diapositiva después de que la diapositiva enfocada se traduzca fuera de la pantalla a la derecha. Cabe señalar que las traducciones xy solo afectan el contenido visual de las diapositivas, las partes interactivas aún están superpuestas una sobre la otra y cubren toda el área de la ventana, bueno ...

Digo casi porque para que el enfoque se active en las diapositivas siguientes y anteriores, con el mouse o el botón táctil, el usuario debe poder acceder a una parte de sus capas interactivas y hacer clic en ellas. El uso de una mezcla de left , right y padding las áreas correctas se puede revelar sin desplazar los elementos visuales.

Por lo tanto, a medida que la diapositiva enfocada actual cambia, también lo hacen las áreas de las capas interactivas que son accesibles. Cada vez que un usuario hace clic en las flechas siguientes o anteriores, en realidad se está enfocando en el elemento <li> adyacente, en lugar de hacer clic en un enlace que realiza cualquier tipo de acción.


útil saber

  1. Para que esto funcione en los navegadores Webkit, se debe tabindex atributo tabindex para que la Pseudo-clase :focus funcione en el elemento base que use para representar una diapositiva.

  2. Debido a los trucos empleados, las diapositivas se reproducirán en orden inverso.

  3. Puede navegar por la presentación de diapositivas utilizando la pestaña, sin embargo, navegará hacia atrás, debido al punto 2. Si tiene una Mac, es posible que deba modificar la configuración del sistema operativo antes de que la pestaña funcione.

  4. Debido al truco a la left y a la right para exponer las flechas de navegación, hay un ligero problema visual cuando se navega hacia adelante, ya que puede ver la siguiente flecha anterior rápidamente animar en su lugar.

  5. Debido a que este sistema funciona en función de :focus siempre que se pierda el enfoque, la presentación de diapositivas vuelve a la diapositiva inicial, por esta razón, los sub enlaces no funcionarán dentro de sus diapositivas, a menos que mejore las interacciones con JavaScript.

  6. Mi demostración utiliza imágenes de fondo SVG, obviamente son opcionales y no funcionan en navegadores antiguos.


Apoyado por

  1. Firefox v26.0 (Mac / PC ~ muy probablemente versiones muy anteriores )
  2. Chrome v32 (Mac / PC ~ muy probablemente versiones anteriores )
  3. Safari v7 (Mac / PC ~ muy probablemente versiones anteriores )
  4. Opera v18 (Mac / PC ~ muy probablemente versiones anteriores )
  5. Internet Explorer 9+ (PC)

IE7 e IE8 ni siquiera pueden entender :last-child o :nth-child entonces no, no funciona para ellos.


extras añadidos

En la demostración a continuación, verá que hay algunos brotes de JavaScript, estos ayudan a mostrar lo que puede hacer la construcción o mejoran progresivamente. Las casillas de verificación, que solo están allí para la demostración, deberían permitirle habilitar o deshabilitar ciertas funciones. Estas características son aplicadas por clases simples:

  1. .with-responsive-images ~ pequeño truco para forzar que las imágenes se ajusten automáticamente.
  2. .with-selection-disabled ~ evita que el usuario arrastre y resalte.
  3. .width-fade-in ~ atenúa la presentación de diapositivas, inicialmente.
  4. .with-reflection ~ permite una reflexión para Firefox y webkit.
  5. .with-slide-zoom ~ on hover las diapositivas se acercarán al ancho máximo.
  6. .with-slide-float ~ en el foco las diapositivas levitarán.
  7. .with-slide-float-hover ~ on hover las diapositivas levitarán.
  8. .con-sombra ~ el reflejo de un poorman.

Tenga en cuenta: el complemento de reflexión se basa en atributos de marcado arbitrarios. Deberá agregar identificadores únicos a cada .slide y luego extender el CSS para tenerlos en cuenta.


Desglose de CSS

preparar

Ok, para empezar, aquí está la configuración básica. En primer lugar, porque mi presentación de diapositivas es con imágenes, he configurado algunos estilos de imagen básicos, todo esto es opcional.

.slide-gfx img { max-width: 600px; max-height: auto; border-radius: 20px; box-shadow: 0 0 80px rgba(255,255,255,1); }

La máscara del control deslizante se agregó como envoltorio a toda la presentación de diapositivas, para evitar que se muestren las barras de desplazamiento de la ventana cuando se opera la presentación de diapositivas en pantalla completa. Esto de nuevo es opcional.

.css-slider-mask { display: block; overflow: hidden; width: 100%; height: 100%; }

Ahora obtenemos la configuración real que se requiere para el control deslizante. Esta primera parte es bastante sencilla, excepto para la display: none; parte. Inicialmente, esto oculta la presentación de diapositivas de todos, pero luego se anula para los navegadores que admiten :nth-child . Es muy probable que su elemento <body> sea ​​el segundo hijo, pero debe verificarlo antes de usar esto.

.css-slider { list-style: none; margin: 0; padding: 0; width: 96%; height: 100%; margin-left: 2%; z-index: 1; } .css-slider { position: relative; display: none; } body:nth-child(2) .css-slider { display: block; }


diapositivas

A continuación bajamos a los detalles de la diapositiva. Debido a la no existencia de un Selector general de hermanos invertido ( ~ ), todos los estilos predeterminados para las diapositivas representan el estado futuro (o siguiente). Esto se debe a que no hay una manera real de seleccionar las diapositivas futuras.

.css-slider .slide { display: block; position: absolute; left: 40px; top: 0; right: 0; bottom: 0; padding-left: 0; padding-right: 40px; z-index: 100; outline: 0; /* kill the focus rect! */ }

Nuevamente, de manera predeterminada, aplicamos el estilo a la flecha hacia adelante y luego anulamos más adelante las diapositivas actuales y pasadas.

.css-slider .slide { background: url(''arrow-right.svg'') no-repeat right center; background-size: 25px auto; } .css-slider .slide:hover { background-image: url(''arrow-right-hover.svg''); cursor: pointer; }

Ahora, la diapositiva enfocada, los elementos clave aquí son :focus (como ya expliqué) y :last-child que no. Last Child se usa en lugar de First Child porque, nuevamente, tenemos que trabajar al revés (todo esto debido a la falta de un Selector General de Hermanos ~ inverso). La razón por la que se necesita cualquiera de los niños es para que podamos "enfocar" una diapositiva inicial cuando no hay un enfoque actual, es decir, en la carga de la página.

.css-slider .slide:target, .css-slider .slide:target:hover, .css-slider .slide:focus, .css-slider .slide:focus:hover, .css-slider .slide:last-child, .css-slider .slide:last-child:hover { left: 40px; right: 40px; padding-left: 0; padding-right: 0; background: transparent; z-index: 101; cursor: default; }

Ahora necesitamos afectar todas las diapositivas que se deslizan en el pasado. He evitado mencionar la :target pseudo-clase :target antes de ahora, básicamente esto se ha implementado para soportar el "salto de navegación". Hay dos razones por las que no voy a cantar las alabanzas del "jump nav":

  1. Está parcialmente alimentado por JavaScript.
  2. Se basa en los valores de #hash o #fragment, que, debido a la creación de estados históricos, pueden alterar la facilidad de uso de su sitio.

De todos modos, el truco para seleccionar diapositivas que están en el pasado depende del Selector general de hermanos . El siguiente constructo básicamente significa seleccionar .slide (s) que encontrarás después del .slide que tiene: focus .

.css-slider .slide:target ~ .slide, .css-slider .slide:focus ~ .slide { padding-left: 40px; padding-right: 0; left: 0; right: 40px; } .css-slider .slide:target ~ .slide, .css-slider .slide:focus ~ .slide { background: url(''arrow-left.svg'') no-repeat left center; background-size: 25px auto; } .css-slider .slide:target ~ .slide:hover, .css-slider .slide:focus ~ .slide:hover { background-image: url(''arrow-left-hover.svg''); }


contenido de la diapositiva

A continuación, debemos controlar qué sucede exactamente con el contenido de nuestra diapositiva. He diseñado este sistema para que, si lo desea, puede omitir la sección de animación. Esto significará que las diapositivas cambiarán instantáneamente. La siguiente parte se encarga de eso.

.css-slider .slide .slide-outer { display: none; width: 100%; height: 100%; }

Slide-inner se utiliza exclusivamente para manejar el centrado de los contenidos de la diapositiva. Se basa en mostrar table y mostrar table-cell .

.css-slider .slide .slide-outer .slide-inner { display: table-cell; vertical-align: middle; text-align: center; width: 100%; height: 100%; }

Slide-gfx es, literalmente, solo una envoltura contenedora para lo que decidas poner en tu presentación. La reflexión se genera a partir de este contenedor, y también se adjuntan algunos otros extras visuales.

.css-slider .slide .slide-outer .slide-inner .slide-gfx { position: relative; display: inline-block; z-index: 102; text-align: left; /* override the centering back to defaults */ }

Esta parte es responsable del cambio instantáneo cuando no se incluye animación.

.css-slider .slide:target .slide-outer, .css-slider .slide:focus .slide-outer, .css-slider .slide:last-child .slide-outer { display: block; /* if they don''t support display table */ display: table; }


anulaciones del último hijo

Debido a las declaraciones de " :last-child " que intervienen cuando no se enfoca nada, si no hiciera más cambios, encontraría que ciertas cosas se rompen. Esto se debe a que :last-child siempre se aplica, a diferencia de :focus . Para rectificar esto necesitamos negar los cambios del :last-child , pero solo cuando algo se ha centrado. Eso es lo que hace el siguiente CSS.

.css-slider .slide:target ~ .slide:last-child, .css-slider .slide:focus ~ .slide:last-child { cursor: pointer; } .css-slider .slide:target ~ .slide:last-child .slide-outer, .css-slider .slide:focus ~ .slide:last-child .slide-outer { display: none; }


molesto truco del índice z final

Hasta ahora el CSS ha sido bastante generalizado, pero siempre hay algo ...

Esta parte solo es necesaria para corregir la capacidad de hacer clic en la flecha de la "diapositiva anterior", de modo que el cuadro anterior más reciente flota por encima de cualquier otra cosa. Si no te importa una acción de diapositiva anterior, puedes eliminar este paso, siempre que ocultes la flecha anterior. Es bastante molesto porque toda esta sección arbitraria podría eliminarse si CSS apoyara una versión invertida del Selector general de hermanos .

Básicamente, lo siguiente admitirá hasta 5 marcos, si necesita más, agregue más. La buena noticia al menos es que puede agregar muchos más marcos de los que necesita sin ningún efecto adverso real. Obviamente, si superas los 100 marcos, deberás ajustar otros índices z en el resto de CSS.

.css-slider .slide:target ~ .slide:nth-child(1), .css-slider .slide:focus ~ .slide:nth-child(1) { z-index:99; } .css-slider .slide:target ~ .slide:nth-child(2), .css-slider .slide:focus ~ .slide:nth-child(2) { z-index:98; } .css-slider .slide:target ~ .slide:nth-child(3), .css-slider .slide:focus ~ .slide:nth-child(3) { z-index:97; } .css-slider .slide:target ~ .slide:nth-child(4), .css-slider .slide:focus ~ .slide:nth-child(4) { z-index:96; } .css-slider .slide:target ~ .slide:nth-child(5), .css-slider .slide:focus ~ .slide:nth-child(5) { z-index:95; }


Animación y complementos

Como he indicado, la animación es opcional, junto con el resto de CSS, es decir, complementos visuales. Incluiré el resto aquí con menos detalle. La mayoría es bastante sencillo una vez que conoce los trucos anteriores y las transiciones o animaciones de CSS. La razón principal de su volumen es, como de costumbre, prefijos de proveedores; que he eliminado por brevedad. Para obtener el código completo de CSS, obviamente puede hacerlo desde la siguiente demostración.

Tenga en cuenta: la mayoría de estos complementos se basan en CSS bastante moderno, es decir, animaciones o SVG.

/** -------------------------------------------------------------------------- * HANDLE THE SLIDE ANIMATION (optional) * ------------------------------------------------------------------------ */ /* Override the default instant slide behaviour */ .css-slider .slide .slide-outer { display: block !important; display: table !important; } /* set up the transitions */ .css-slider .slide .slide-outer { transition-property: opacity, transform; transition-duration: 2s; transition-timing-function: ease; } /* After state */ .css-slider .slide:target ~ .slide .slide-outer, .css-slider .slide:target ~ .slide:last-child .slide-outer, .css-slider .slide:focus ~ .slide .slide-outer, .css-slider .slide:focus ~ .slide:last-child .slide-outer { transform: translate(-150%,0); transform: translate3D(-150%,0,0); } /* Before state */ .css-slider .slide .slide-outer { transform: translate(200%,0); transform: translate3D(200%,0,0); } /* Focused state*/ .css-slider .slide:target .slide-outer, .css-slider .slide:focus .slide-outer, .css-slider .slide:last-child .slide-outer { transform: translate(0,0); transform: translate3D(0,0,0); } /** -------------------------------------------------------------------------- * SMALL SCREEN FIX / SLIDE JERK (optional) * --------------------------------------------------------------------------- * When we shift ''left'' and ''right'' values -- in order to allow access to a future * or past arrow -- this can cause a jump in the responsive scaling of the slide. * if we transition the left value quickly, it can make this appear less jarring. */ .css-slider .slide { transition-property: left, padding-left; transition-duration: 1s; transition-timing-function: ease; } /** -------------------------------------------------------------------------- * Add-on module : responsive images * ------------------------------------------------------------------------ */ .with-responsive-images .slide-gfx img { width: 100%; height: auto; } /** -------------------------------------------------------------------------- * Add-on module : stop user selection * ------------------------------------------------------------------------ */ /* if your slides don''t need to be selectable, I recommend using this */ .with-selection-disabled { user-select: none; } /** -------------------------------------------------------------------------- * Add-on module : initial fade in * ------------------------------------------------------------------------ */ .with-fade-in .slide-gfx { opacity: 0; } /* animate into visibility */ .with-fade-in .slide-gfx { animation: css-slideshow-fade-in 2s; animation-delay: 1s; animation-fill-mode: forwards; } /* Vebdor animations */ @keyframes css-slideshow-fade-in { from { opacity: 0; } to { opacity: 1; } } /** -------------------------------------------------------------------------- * Add-on module : slide reflection * ------------------------------------------------------------------------ */ /* force our slide-gfx to be inline-block and relative positioned */ .with-reflection .slide-gfx { display: inline-block !important; } /* reflection for webkit agents */ .with-reflection .slide-gfx > *:first-child { -webkit-box-reflect: below 2px -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.9, transparent), to(white)); } /* make sure internal images don''t keep inline spacing/margin */ .with-reflection .slide-gfx img { display: block; } /* generate the reflection */ .with-reflection .slide-gfx:after { content: ''''; position: absolute; display: block; mask: url("reflection-mask.svg#mask"); /* gradient fade the reflection */ transform: scaleY(-1); /* flip clone to appear as reflection */ opacity: 0.5; /* fade out reflection */ top: 100%; width: 100%; height: 60px; z-index: 200; margin-top: 2px; } /* again, due to element() requiring IDs we need arbitrary code per each slide and each slide-gfx needs an id */ .with-reflection #s1:after { background: -moz-element(#s1) no-repeat left bottom; } .with-reflection #s2:after { background: -moz-element(#s2) no-repeat left bottom; } .with-reflection #s3:after { background: -moz-element(#s3) no-repeat left bottom; } .with-reflection #s4:after { background: -moz-element(#s4) no-repeat left bottom; } .with-reflection #s5:after { background: -moz-element(#s5) no-repeat left bottom; } .with-reflection #s6:after { background: -moz-element(#s6) no-repeat left bottom; } .with-reflection #s7:after { background: -moz-element(#s7) no-repeat left bottom; } .with-reflection #s8:after { background: -moz-element(#s8) no-repeat left bottom; } .with-reflection #s9:after { background: -moz-element(#s9) no-repeat left bottom; } .with-reflection #s10:after { background: -moz-element(#s10) no-repeat left bottom; } .with-reflection #s11:after { background: -moz-element(#s11) no-repeat left bottom; } .with-reflection #s12:after { background: -moz-element(#s12) no-repeat left bottom; } .with-reflection #s13:after { background: -moz-element(#s13) no-repeat left bottom; } .with-reflection #s14:after { background: -moz-element(#s14) no-repeat left bottom; } .with-reflection #s15:after { background: -moz-element(#s15) no-repeat left bottom; } .with-reflection #s16:after { background: -moz-element(#s16) no-repeat left bottom; } .with-reflection #s17:after { background: -moz-element(#s17) no-repeat left bottom; } .with-reflection #s18:after { background: -moz-element(#s18) no-repeat left bottom; } .with-reflection #s19:after { background: -moz-element(#s19) no-repeat left bottom; } .with-reflection #s20:after { background: -moz-element(#s20) no-repeat left bottom; } /** -------------------------------------------------------------------------- * Add-on module : slide zoom (optional, not compatible with slide float) * ------------------------------------------------------------------------ */ .with-slide-zoom .slide .slide-gfx > *:first-child { transition-property: max-width; transition-duration: 2s; transition-timing-function: ease-in-out; transition-delay: 0.25s; } .with-slide-zoom .slide .slide-gfx > *:first-child:hover { max-width: 1000px; } /** -------------------------------------------------------------------------- * Add-on module : slide float (optional, not compatible with slide zoom) * ------------------------------------------------------------------------ */ /* inital transition set-up */ .with-slide-float:not(.with-slide-zoom) .slide .slide-gfx > *:first-child, .with-slide-float-hover:not(.with-slide-zoom) .slide .slide-gfx > *:first-child { transition-property: transform; transition-duration: 2s; transition-timing-function: ease-in-out; } /* we need a delay for the non-hover version */ .with-slide-float:not(.with-slide-zoom) .slide .slide-gfx > *:first-child { transition-delay: 2s; } /* initial levitation on focus */ .with-slide-float:not(.with-slide-zoom) .slide:target .slide-gfx > *:first-child, .with-slide-float:not(.with-slide-zoom) .slide:focus .slide-gfx > *:first-child, .with-slide-float-hover:not(.with-slide-zoom) .slide .slide-gfx > *:first-child:hover { transform: translate(0,-40px); transform: translate3D(0,-40px,0); } /* trigger the float animation after 4s */ .with-slide-float:not(.with-slide-zoom) .slide:target .slide-gfx > *:first-child, .with-slide-float:not(.with-slide-zoom) .slide:focus .slide-gfx > *:first-child, .with-slide-float-hover:not(.with-slide-zoom) .slide .slide-gfx > *:first-child:hover { animation: css-slideshow-levitate 4s; animation-direction: alternate; animation-fill-iteration-count: infinite; animation-timing-function: ease-in-out; animation-delay: 2s; } /* longer delay for automatic version i.e. non-hover */ .with-slide-float:not(.with-slide-zoom) .slide:target .slide-gfx > *:first-child, .with-slide-float:not(.with-slide-zoom) .slide:focus .slide-gfx > *:first-child { animation-delay: 4s; } /* Vebdor animations for the float */ @keyframes css-slideshow-levitate { from { transform: translate(0,-40px); transform: translate3D(0,-40px,0); } to { transform: translate(0,-20px); transform: translate3D(0,-20px,0); } } /** -------------------------------------------------------------------------- * Add-on module : ground shadow (optional) * ------------------------------------------------------------------------ */ .with-shadow .slide .slide-gfx:before { content: ''''; background: url(''slide-shadow.svg'') no-repeat center center; position: absolute; bottom: -10px; left: -20px; right: -20px; height: 20px; z-index: -1; opacity: 0.7; } .with-shadow.with-slide-float .slide .slide-gfx:before, .with-shadow.with-slide-float-hover .slide .slide-gfx:before { transition-property: opacity; transition-duration: 2s; transition-timing-function: ease-in-out; } .with-shadow.with-slide-float .slide .slide-gfx:before { transition-delay: 2s; } .with-shadow.with-slide-float .slide:target .slide-gfx:before, .with-shadow.with-slide-float .slide:focus .slide-gfx:before, .with-shadow.with-slide-float .slide:last-child .slide-gfx:before, .with-shadow.with-slide-float-hover .slide .slide-gfx:hover:before { opacity: 0.1; animation: css-slideshow-shadow 4s; animation-delay: 4s; animation-direction: alternate; animation-fill-iteration-count: infinite; animation-timing-function: ease-in-out; } .with-shadow.with-slide-float-hover .slide .slide-gfx:hover:before { animation-delay: 2s; } /* Vebdor animations for the float */ @keyframes css-slideshow-shadow { from { opacity: 0.1; } to { opacity: 0.7; } }


ejemplo implementado (v0.2)

http://codelamp.co.uk/css-slideshow/v0.2/

tenga en cuenta: el navegador de salto, es decir, los puntos circulares, se basan en un poco de JavaScript. El resto es puro CSS.


versión previa

Como dije, ha tomado bastante tiempo refinar este sistema. Para aquellos que puedan estar interesados, aquí está mi (última) versión 0.1 - ha habido muchas antes;) Esto tuvo un enfoque ligeramente diferente e involucró partes móviles tanto visuales como interactivas. Al final lo deseché porque implicaba más procesamiento del navegador y, por lo tanto, era mucho más torpe; algo que esta demo de color sólido no revela.

http://jsfiddle.net/3cyP8/7/

Desde hace algún tiempo, de vez en cuando, he estado intentando implementar una presentación de diapositivas solo para CSS, una que:

  1. Oferta de navegación hacia adelante y hacia atrás.
  2. No modificar el historial de navegación.
  3. Inculcar una dirección distinta al movimiento del contenido.
  4. Trabaja en tantos navegadores como sea posible.

La mayoría de las demás presentaciones de diapositivas de CSS que he encontrado no han marcado todas esas casillas.

Afortunadamente, me ha llevado tanto tiempo que los navegadores mismos han mejorado su no-end, hasta el punto en que ahora es bastante posible, aunque con algunos CSS-ismos "modernos". En caso de que sea útil para alguien más, pensé en publicarlo aquí.

Entonces, ¿cómo puede crear una presentación de diapositivas navegable, utilizando solo CSS y el siguiente marcado?

<ul class="css-slider"> <li class="slide"><img src="photos/a.jpg" /></li> <li class="slide"><img src="photos/b.jpg" /></li> <li class="slide"><img src="photos/c.jpg" /></li> <li class="slide"><img src="photos/d.jpg" /></li> <li class="slide"><img src="photos/e.jpg" /></li> </ul>