2015-05-07 9 views
20

PLAYGROUND HERECome modellare i pulsanti di opzione in modo diverso se si adattano a una singola riga?

Mi piacerebbe abbinare i pulsanti di opzione in modo diverso se si inseriscono in una singola riga. Ad esempio:

enter image description here

Il primo contenitore non ha spazio sufficiente per adattarsi a tutti i pulsanti di opzione in un'unica fila. Pertanto, appaiono verticalmente come normali pulsanti radio.

Il secondo contenitore ha spazio sufficiente. Pertanto, i pulsanti radio appaiono come pulsanti.

È possibile ottenere questo comportamento utilizzando solo il codice CSS?

In caso contrario, Javascript "hack" è il benvenuto.

PLAYGROUND HERE


HTML

<div class="container radio"> 
    <div> 
    <input id="a1" type="radio" name="radio"> 
    <label for="a1">Yes,</label> 
    </div> 
    <div> 
    <input id="a2" type="radio" name="radio"> 
    <label for="a2">it</label> 
    </div> 
    <div> 
    <input id="a3" type="radio" name="radio"> 
    <label for="a3">is</label> 
    </div> 
    <div> 
    <input id="a4" type="radio" name="radio"> 
    <label for="a4">possible</label> 
    </div> 
    <div> 
    <input id="a5" type="radio" name="radio"> 
    <label for="a5">to</label> 
    </div> 
    <div> 
    <input id="a6" type="radio" name="radio"> 
    <label for="a6">achieve</label> 
    </div> 
    <div> 
    <input id="a7" type="radio" name="radio"> 
    <label for="a7">this</label> 
    </div> 
</div> 
<div class="container buttons"> 
    <div> 
    <input id="b1" type="radio" name="buttons"> 
    <label for="b1">Yes,</label> 
    </div> 
    <div> 
    <input id="b2" type="radio" name="buttons"> 
    <label for="b2">it</label> 
    </div> 
    <div> 
    <input id="b3" type="radio" name="buttons"> 
    <label for="b3">is</label> 
    </div> 
    <div> 
    <input id="b4" type="radio" name="buttons"> 
    <label for="b4">possible</label> 
    </div> 
</div> 

CSS (LESS)

.container { 
    display: flex; 
    width: 220px; 
    padding: 20px; 
    margin-top: 20px; 
    border: 1px solid black; 

    &.radio { 
    flex-direction: column; 
    } 

    &.buttons { 
    flex-direction: row; 

    > div { 
     input { 
     display: none; 

     &:checked + label { 
      background-color: #ADFFFE; 
     } 
     } 

     label { 
     padding: 5px 10px; 
     margin: 0 1px; 
     background-color: #ccc; 
     } 
    } 
    } 
} 
+0

Mentre il collegamento alla riproduzione del JS Bin è molto apprezzato, è necessario inserire il codice pertinente nella domanda stessa per proteggersi da link-rot. Se il tuo obiettivo è quello di fornire una demo (di nuovo: molto apprezzata!), Puoi semplicemente utilizzare "[Stack Snippet] [Overwriting Frammento] di Stack Overflow (http://blog.stackoverflow.com/2014/09/introducing-runnable-javascript-css- e-html-code-snippets /) "funzionalità. –

risposta

23

Non possibile in CSS, ma non ci vuole molto JavaScript.

In CSS, aggiungere flex-shrink: 0 a > div. Ciò impedirà ai bambini di .container di ridursi in misura inferiore alla loro estensione.

In JavaScript:

  1. Applicare la classe buttons.
  2. Utilizzare Element.getBoundingClientRect per determinare se l'ultimo figlio di .container non rientra nell'estensione di .container. In tal caso, passare alla classe radio. (È inoltre necessario prendere l'imbottitura giusta in considerazione. Grazie a @Moob per la segnalazione.)

Javascript

var container = document.querySelector('.container'), 
    lastChild= document.querySelector('.container > :last-child'), 
    paddingRight= parseInt(window.getComputedStyle(container, null).getPropertyValue('padding-right')), 
    timer; 

window.onresize = function() { 
    clearTimeout(timer); 
    timer= setTimeout(function() { 
    container.classList.remove('radio'); 
    container.classList.add('buttons'); 
    if (container.getBoundingClientRect().right-paddingRight < 
     lastChild.getBoundingClientRect().right) { 
     container.classList.add('radio'); 
     container.classList.remove('buttons'); 
    } 
    }); 
} 

Updated JSBin

+1

Buona soluzione. Non sapevo di 'flex-shrink' (evitando ancora i flex-box nella maggior parte del mio lavoro). L'ho usato per migliorare la mia risposta. Grazie. – Moob

+0

@Rick Nice! Ho provato a eseguire il tuo JS ogni volta che ridimensiona la finestra, ma vedo uno strano effetto sfarfallio: http://jsbin.com/garuvexaha/1/edit?html,js,output Qualche idea di cosa c'è che non va? –

+0

"onresize" viene eseguito costantemente durante il ridimensionamento. Meglio aggiungere un timeout. Vedi l'aggiornamento su http://jsbin.com/cibudaforu/1/edit?html,js,output –

-1

c'è abbastanza soluzione CSS solo, ma devi sapere la massima quantità di EL ements in row. Si basa sul contatore, ma non su dimensioni reali.

Ad esempio, se si è sicuri, che si può mettere 4 elementi in una riga, in ogni caso, è possibile utilizzare i seguenti selettore:

se importo è più minore o uguale 4:

div:nth-last-child(-n+5):first-child, 
div:nth-last-child(-n+5):first-child ~ div { 
    } 

se l'importo è più quindi 4:

div:nth-last-child(n+5), 
div:nth-last-child(n+5) ~ div { 
} 

provare questo: http://jsbin.com/fozeromezi/2/edit (basta rimuovere/aggiungere div)

+0

... ma se gli elementi sono di larghezza sconosciuta o disuguale non avremmo modo di sapere quanti ne saranno adatti. – Moob

+0

Dipende. È sempre possibile utilizzare "ellissi di overflow" in combinazione con "display inline-block" e larghezza fissa. Ecco perché ho detto che questa risposta è adatta solo per determinate condizioni, ma è in puro CSS. – Andriy

1

Se ho capito bene cosa stai chiedendo, puoi modificare la tua porzione flex-direction a row invece di column. Questo li farà allinearsi all'interno della scatola.

Dovrai fare un po 'di stile in più per far apparire correttamente le etichette nel modo desiderato, ma questo dovrebbe metterle in fila per te. I've updated the playground with my changes.

+0

Ho paura di aver frainteso la domanda. Nel mio esempio ci sono due contenitori. Uno di loro ha la 'radio' di classe, e l'altro' pulsanti'. Non voglio avere queste lezioni sui contenitori. Li ho aggiunti solo per scopi dimostrativi. La domanda è come creare il comportamento che vedi nella demo senza aggiungere manualmente queste classi. –

+0

Ahh ok. Ora capisco. Aggiornerò la mia risposta di conseguenza – BDD

7

non riesco a pensare a un CSS unica soluzione ma si potrebbe usare JS per verificare se le voci si adatterebbe in una riga e applicare la 'Radio' o classname 'pulsanti' di conseguenza:

Perdonate la mia ruvida JS - la sua poco elegante e per i browser moderni solo, ma si ottiene l'idea:

var containers = document.querySelectorAll(".container"), 
test = function(){ 
    for (i = 0; i < containers.length; ++i) { 
     var container = containers[i], 
      divs = container.querySelectorAll("div"), 
      iw = 0; 
     container.classList.remove("radio"); 
     container.classList.add("buttons"); 
     //get the sum width of the div 
     for (d = 0; d < divs.length; ++d) { 
     iw+=divs[d].offsetWidth; 
     } 
     var style = window.getComputedStyle(container, null); 
     var ow = parseInt(style.getPropertyValue("width")); 
     if(ow<=iw){ 
      container.classList.add("radio"); 
      container.classList.remove("buttons");    
     } 
    } 
}; 

window.onresize = function(event) { 
    test(); 
}; 
test(); 

http://jsbin.com/zofixakama/3/edit?html,css,js,output
(ridimensionare la finestra/pannello per vedere l'effetto)

Aggiornamento: Se si aggiunge .container div {flex-shrink:0;} allo stile, il JS può essere molto più semplice in quanto non è necessario misurare la larghezza combinata dei div (grazie @ rick-hitchcock). Tuttavia, sebbene il codice sia più elegante, non prende in considerazione il numero padding del contenitore.

See: http://jsbin.com/zofixakama/5/edit?html,css,js,output

+0

@ humble.rumble.6x3 concordato, la versione aggiornata (v5) non prende in considerazione il padding, tuttavia l'esempio di codice (e il collegamento a v3) lo fa. Ho aggiornato la mia risposta per riflettere questo. Grazie. – Moob

1

Provate il seguente esempio ... ........... ------------ HTML -----------

<html> 
<head> 
<link rel="stylesheet" href="style.css" type="text/css" /> 
</head> 
<body> 
    <div class="table-row"> 
     <div class="col"> 
       <input type="Radio">This 
      </div> 
      <div class="col" style="padding-top: 2px;"> 
       <input type="Radio">Is 
      </div> 

      <div class="col"> 
       <input type="Radio">Simply 
      </div> 
      <div class="col" style="padding-top: 2px;"> 
       <input type="Radio">Possible 
      </div> 

     </div> 
</body> 
</html> 

------- CSS -------------

.table-row{ 
    display:table-row;  
    /* text-align: center; */ 
} 
.col{ 
    display:table-cell; 
    /* border: 1px solid #CCC; */ 
} 
1

non funzionerebbe per testare per la larghezza poi, se necessario rimuovere l'icona pulsante e sostituirla con una grafica o forma?

.checkbox { 
    display:none; 
} 

.label { 
    display: inline-block; 
    height: 20px; 
    background: url('picture.png'); 
} 

Probabilmente non è così semplice, ma io uso che per caselle di controllo e sembra funzionare in quella situazione.

1

È possibile ottenere questo risultato solo utilizzando CSS e senza necessità di script.

HTML: è necessario inserire l'input all'interno del tag che conterrà il testo.

CSS: Qui in CSS dovremo nascondere il pulsante di opzione, in modo che solo il testo sia visibile. Quando l'utente fa clic sul testo, in realtà fa clic sul pulsante di opzione.

div lable input#a1{ 
    display:none; 
} 
Problemi correlati