Div de recolher / expandir CSS puro


87

Eu tenho um div recolhível CSS puro que é baseado no código de outra pessoa que usa o :targetpsuedoclass. O que estou tentando configurar é uma página com mais de 12 perguntas e, quando você clica no botão +, a div de resposta se expande abaixo. Não consigo descobrir como fazer vários elementos div de colapso nesta página sem escrever uma tonelada de CSS extra. Alguém tem sugestões sobre como escrever isso para que meu código CSS seja minimizado? (ou seja, eu não preciso inserir um monte de seletores exclusivos para cada uma das 12+ questões).

Não posso usar Javascript, pois isso vai para um site wordpress.com que não permite JS.

Aqui está meu 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;
}

6
Para qualquer pessoa que vê isso sem usar o wordpress, posso dizer POR FAVOR, NÃO FAÇA ISSO. É um hack e quebra a funcionalidade de trás de uma página, o que é super irritante.
gbtimmon

Respostas:


102

Dependendo de quais navegadores / dispositivos você está procurando oferecer suporte, ou o que você está preparado para tolerar em navegadores não compatíveis, você pode verificar as tags <summary>e <detail>. Eles são exatamente para esse propósito. Nenhum css é necessário, pois o recolhimento e a exibição fazem parte da definição / formatação das tags.

Fiz um exemplo aqui :

<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>

O suporte do navegador varia. Experimente no webkit para obter melhores resultados. Outros navegadores podem mostrar por padrão todas as soluções. Você pode talvez recorrer ao método ocultar / mostrar descrito acima.


1
Bug 591737 é o bug que rastreia o suporte no Firefox.
ShreevatsaR

9
Estamos quase em meados de 2016 e não existe suporte para isso. Definitivamente, não use essa solução.
Dwayne Charrington

3
O suporte @DigitalSea sendo 'inexistente' é incorreto e 'definitivamente não use esta solução' são palavras fortes para um padrão que foi estável por vários anos e teve um polyfill disponível desde 2010 mathiasbynens.be/notes/html5-details- jquery . Qual é a base do seu argumento? O MS edge provavelmente implementará essas tags em breve. O Firefox implementou tags de resumo / detalhes (mas atualmente as tem por trás de uma bandeira). O Webkit suporta como padrão desde o Chrome 12, assim como o safari nos navegadores OS X e iOS Blink derivados - Chrome mobile / desktop, Opera suportá-lo como padrão
Thurstan

1
@Thurstan Sem suporte em; IE8, IE9, IE10, IE11, Edge 13, sem suporte no Firefox até agosto de 2016. Portanto, a menos que você tenha o luxo de abrir mão do suporte do IE inteiramente e atualmente Edge e Firefox, sim, não são bem suportados. O polyfill essencialmente faz o que você já pode fazer com Javascript (sem jQuery) e de forma bastante eficiente. Um polyfill para este recurso fácil de implementar é um exagero. A solução que você vinculou usa jQuery, o que é desnecessário. Eu não ficaria surpreso se vermos isso removido da especificação algum dia.
Dwayne Charrington

4
Estou desenvolvendo apenas para navegadores modernos e essa técnica funcionou perfeitamente para o meu caso de uso, e não exigiu uma lambida de CSS!
Josh Habdas

39

Usando <summary>e<details>

Usar os elementos <summary>e <details>é o mais simples, mas veja o suporte do navegador, pois o IE atual não o oferece. Você pode polyfill embora (a maioria é baseada em jQuery). Observe que o navegador não suportado simplesmente mostrará a versão expandida do curso, de modo que pode ser aceitável em alguns 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>

Veja também como definir o estilo do <details>elemento (HTML5 Doctor) (um pouco complicado).

CSS3 puro

O :targetseletor tem um suporte de navegador muito bom e pode ser usado para fazer um único elemento recolhível dentro do quadro.

.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>


1
<summary>e <details>ainda não funciona em todos os principais navegadores.
Neurotransmissor

3
@TranslucentCloud Foi o que eu disse. ;)
Wernight

E também isso foi dito pelo autor da outra resposta.
Neurotransmissor

1
Existe alguma maneira de adicionar animação de transição a isso?
Aziz Javed

1
Para a versão animada em que o texto desliza para baixo e desaparece usando a transição CSS, consulte esta postagem do blog
sketchyTech

23

A resposta de @gbtimmon é ótima, mas muito, muito complicada. Simplifiquei seu código o máximo que 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>


3
Trabalhar com CSS3 é tão gratificante às vezes :-)
mrmut

Isso não funciona quando usado mais de uma vez na mesma página: clicar em ocultar / mostrar afeta todos os divs. Alguém sabe como modificá-lo para que funcione quando usado mais de uma vez?
phhu 01 de

Atualização: CSS de @Wernight responde apenas abaixo ("Pure CSS3", CSS semelhante a este, mas usando classes). funciona com vários divs na mesma página.
phhu 01 de

1
@phhu sim, não funcionará se você reutilizar os mesmos IDs. Ele vai funcionar se você vai introduzir outro conjunto de IDs ( hide2, show2, answer2por exemplo). Ou aulas, não importa.
Neurotransmissor

21

Você só precisa iterar as âncoras nos dois links.

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

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

Eu também adicionei alguma margem à chamada do FAQ para melhorar o formato.


Obrigado! Eu tentei isso, mas por algum motivo não funcionou para mim. Deve ter tido um bug que nunca peguei.
dmarvs

17

Ou uma versão super simples com quase nenhum 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/


Por falar nisso, esqueci de mencionar que: o target não funciona no IE8 ou mais antigo, surpresa surpresa! E css PIE também não ajuda com isso, então você pode querer olhar para uma opção jQuery se a compatibilidade do navegador for de seu interesse.
Ionko Gueorguiev

Obrigado, isso é muito mais limpo. Cerca de um terço do nosso público-alvo potencial estará no IE8. Eu estava pensando em apenas adicionar algum CSS condicional que apenas abriria todos os divs no carregamento.
dmarvs

Acho que uma interface com guias pode ser a solução certa para você. Eu fiz um há algum tempo, você pode fazer o download / verificar aqui: ionko.com/index.php/work/simple-and-flexible-tabs .
Ionko Gueorguiev
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.