CSS puro contraer / expandir div

91

Tengo un div plegable CSS puro que se basa en el código de otra persona que usa la :targetpsuedoclass. Lo que estoy tratando de configurar es una página con más de 12 preguntas, y cuando haces clic en el botón +, el div de respuesta se expande debajo. No puedo averiguar cómo hacer varios elementos div que se colapsan en esta página sin escribir un montón de CSS adicional. ¿Alguien tiene sugerencias sobre cómo escribir esto para que mi código CSS se minimice? (es decir, no tengo que ingresar un montón de selectores únicos para cada una de las más de 12 preguntas).

No puedo usar Javascript ya que esto va en un sitio de wordpress.com que no permite JS.

Aquí está mi jfiddle: http://jsfiddle.net/dmarvs/94ukA/4/

<div class="FAQ">
    <a href="#hide1" class="hide" id="hide1">+</a>
    <a href="#show1" class="show" id="show1">-</a>
    <div class="question"> Question Question Question Question Question Question Question Question Question Question Question? </div>
        <div class="list">
            <p>Answer Answer Answer Answer Answer Answer Answer Answer Answer Answer Answer Answer Answer Answer Answer Answer Answer Answer </p>
        </div>
</div>
/* source: http://www.ehow.com/how_12214447_make-collapsing-lists-java.html */

.FAQ { 
    vertical-align: top; 
    height:auto !important; 
}
.list {
    display:none; 
    height:auto;
    margin:0;
    float: left;
}
.show {
    display: none; 
}
.hide:target + .show {
    display: inline; 
}
.hide:target {
    display: none; 
}
.hide:target ~ .list {
    display:inline; 
}

/*style the (+) and (-) */
.hide, .show {
    width: 30px;
    height: 30px;
    border-radius: 30px;
    font-size: 20px;
    color: #fff;
    text-shadow: 0 1px 0 #666;
    text-align: center;
    text-decoration: none;
    box-shadow: 1px 1px 2px #000;
    background: #cccbbb;
    opacity: .95;
    margin-right: 0;
    float: left;
    margin-bottom: 25px;
}

.hide:hover, .show:hover {
    color: #eee;
    text-shadow: 0 0 1px #666;
    text-decoration: none;
    box-shadow: 0 0 4px #222 inset;
    opacity: 1;
    margin-bottom: 25px;
}

.list p{
    height:auto;
    margin:0;
}
.question {
    float: left;
    height: auto;
    width: 90%;
    line-height: 20px;
    padding-left: 20px;
    margin-bottom: 25px;
    font-style: italic;
}
dmarvs
fuente
6
A cualquiera que vea esto y no use WordPress, ¿puedo decirle POR FAVOR NO HAGA ESTO? Es un truco y rompe la funcionalidad posterior de una página, lo cual es súper molesto.
gbtimmon

Respuestas:

104

Dependiendo de los navegadores / dispositivos que esté buscando admitir, o de lo que esté dispuesto a soportar para los navegadores que no cumplen, es posible que desee revisar las etiquetas <summary>y <detail>. Son exactamente para este propósito. No se requiere CSS en absoluto, ya que el colapso y la visualización son parte de la definición / formato de las etiquetas.

He hecho un ejemplo aquí :

<details>
<summary>This is what you want to show before expanding</summary>
<p>This is where you put the details that are shown once expanded</p>
</details>

El soporte del navegador varía. Pruebe webkit para obtener mejores resultados. Otros navegadores pueden mostrar de forma predeterminada todas las soluciones. Quizás pueda recurrir al método ocultar / mostrar descrito anteriormente.

Thurstan
fuente
2
El error 591737 es el error que rastrea el soporte en Firefox.
ShreevatsaR
9
Es casi mediados de 2016 y el soporte para esto es inexistente. Definitivamente no uses esta solución.
Dwayne Charrington
3
El soporte de @DigitalSea es 'inexistente' es incorrecto y 'definitivamente no use esta solución' son palabras fuertes para un estándar que ha sido estable durante varios años y ha tenido un polyfill disponible desde 2010 mathiasbynens.be/notes/html5-details- jquery . ¿Cuál es la base de su argumento? Es probable que MS edge implemente estas etiquetas pronto. Firefox ha implementado etiquetas de resumen / detalle (pero actualmente las tiene detrás de una bandera). Webkit lo admite de forma predeterminada desde Chrome 12, al igual que Safari en OS X y navegadores derivados de iOS Blink: Chrome móvil / escritorio, ópera lo admite como predeterminado
Thurstan
1
@Thurstan Sin apoyo en; IE8, IE9, IE10, IE11, Edge 13, sin soporte en Firefox hasta agosto de 2016. Por lo tanto, a menos que tenga el lujo de renunciar al soporte de IE por completo y actualmente Edge y Firefox, sí, no es muy compatible. El polyfill esencialmente hace lo que ya puede hacer con Javascript (sin jQuery) y de manera bastante eficiente. Un polyfill para esta característica fácil de implementar es excesivo. La solución que vinculó usa jQuery, que es innecesario. De todos modos, no me sorprendería que un día veamos esto eliminado de la especificación.
Dwayne Charrington
4
Estoy desarrollando solo para navegadores modernos y esta técnica funcionó perfectamente para mi caso de uso, ¡y no requirió una pizca de CSS!
Josh Habdas
39

Usando <summary>y<details>

El uso de los elementos <summary>y <details>es el más simple, pero vea el soporte del navegador ya que el IE actual no lo admite. Sin embargo, puede realizar un polyfill (la mayoría están basados ​​en jQuery). Tenga en cuenta que el navegador no compatible simplemente mostrará la versión ampliada, por supuesto, por lo que puede ser aceptable en algunos casos.

/* Optional styling */
summary::-webkit-details-marker {
  color: blue;
}
summary:focus {
  outline-style: none;
}
<details>
  <summary>Summary, caption, or legend for the content</summary>
  Content goes here.
</details>

Vea también cómo diseñar el <details>elemento (HTML5 Doctor) (un poco complicado).

CSS3 puro

El :targetselector tiene un soporte de navegador bastante bueno y se puede usar para crear un solo elemento plegable dentro del marco.

.details,
.show,
.hide:target {
  display: none;
}
.hide:target + .show,
.hide:target ~ .details {
  display: block;
}
<div>
  <a id="hide1" href="#hide1" class="hide">+ Summary goes here</a>
  <a id="show1" href="#show1" class="show">- Summary goes here</a>
  <div class="details">
    Content goes here.
  </div>
</div>
<div>
  <a id="hide2" href="#hide2" class="hide">+ Summary goes here</a>
  <a id="show2" href="#show2" class="show">- Summary goes here</a>
  <div class="details">
    Content goes here.
  </div>
</div>

Wernight
fuente
1
<summary>y <details>aún no funciona en todos los navegadores principales.
Neurotransmisor
4
@TranslucentCloud Eso es lo que dije. ;)
Wernight
Y también lo dijo el autor de la otra respuesta.
Neurotransmisor
1
¿Hay alguna forma de agregar animación de transición a esto?
azizj1
1
Para la versión animada, donde diapositivas de texto hacia abajo y se desvanece en el uso de transición CSS, ven esta entrada de blog
sketchyTech
25

La respuesta de @ gbtimmon es genial, pero demasiado complicada. He simplificado su código tanto como pude.

#answer,
#show,
#hide:target {
    display: none; 
}

#hide:target + #show,
#hide:target ~ #answer {
    display: inherit; 
}
<a href="#hide" id="hide">Show</a>
<a href="#/" id="show">Hide</a>
<div id="answer"><p>Answer</p></div>

Neurotransmisor
fuente
3
Trabajar con CSS3 es muy gratificante a veces :-)
mrmut
Esto no funciona cuando se usa más de una vez en la misma página: hacer clic en ocultar / mostrar afecta a todos los divs. ¿Alguien sabe cómo modificarlo para que funcione cuando se usa más de una vez?
phhu
Actualización: El CSS de @Wernight solo responde a continuación ("CSS3 puro", CSS similar a este, pero usando clases). funciona con múltiples divs en la misma página.
phhu
1
@phhu sí, no funcionará si reutiliza los mismos ID. Se trabajará si va a introducir otro conjunto de ID ( hide2, show2, answer2por ejemplo). O clases, no importa.
Neurotransmisor
22

Solo necesita iterar los anclajes en los dos enlaces.

<a href="#hide2" class="hide" id="hide2">+</a>
<a href="#show2" class="show" id="show2">-</a>

Vea este jsfiddle http://jsfiddle.net/eJX8z/

También agregué algo de margen a la llamada de preguntas frecuentes para mejorar el formato.

gbtimmon
fuente
¡Gracias! Lo había intentado, pero por alguna razón no funcionó para mí. Debe haber tenido un error que nunca cogí.
dmarvs
18

O una versión súper simple sin apenas css :)

<style>   
.faq ul li {
    display:block;
    float:left;
    padding:5px;
}

.faq ul li div {
    display:none;
}

.faq ul li div:target {
    display:block;
}


</style>


<div class="faq">
   <ul>
   <li><a href="#question1">Question 1</a>   
   <div id="question1">Answer 1 </div>
   </li>


   <li><a href="#question2">Question 2</a>
   <div id="question2">Answer 2 </div>
   </li>
   <li><a href="#question3">Question 3</a>
   <div id="question3">Answer 3 </div>
   </li>
   <li><a href="#question4">Question 4</a>
   <div id="question4">Answer 4 </div>
   </li>
   <li><a href="#question5">Question 5</a>
   <div id="question5">Answer 5 </div>
   </li>
   <li><a href="#question6">Question 6</a>
   <div id="question6">Answer 6 </div>
   </li>
   </ul>  
</div>

http://jsfiddle.net/ionko22/4sKD3/

Ionko Gueorguiev
fuente
Por cierto, olvidé mencionar que: el destino no funciona en IE8 o versiones anteriores, ¡sorpresa sorpresa! Y css PIE tampoco ayudará con eso, por lo que es posible que desee ver una opción de jQuery si la compatibilidad del navegador es de su interés.
Ionko Gueorguiev
Gracias, eso es mucho más limpio. Aproximadamente un tercio de nuestro público objetivo potencial estará en IE8. Estaba pensando en agregar algo de CSS condicional que simplemente abriría todos los divs al cargar.
dmarvs
Creo que una interfaz con pestañas podría ser la solución adecuada para ti. Hice uno hace un tiempo, puedes descargarlo / verlo aquí: ionko.com/index.php/work/simple-and-flexible-tabs .
Ionko Gueorguiev