html - tricks - Come fai a impedire ai genitori di elementi fluttuanti di crollare?




flexbox (11)

Questa domanda ha già una risposta qui:

Sebbene elementi come <div> solito crescano per adattarsi ai loro contenuti, l'uso della proprietà float può causare un problema sorprendente per i principianti CSS: se gli elementi flottati hanno elementi padre non flottati, il genitore crollerà.

Per esempio:

  <div>
        <div style="float: left;">Div 1</div>
        <div style="float: left;">Div 2</div>
    </div>

Il div genitore in questo esempio non si espande per contenere i figli flottati: sembrerà avere height: 0 .

Come risolvi questo problema?

Mi piacerebbe creare un elenco esaustivo di soluzioni qui. Se si è a conoscenza di problemi di compatibilità tra browser, si prega di indicarli.

Soluzione 1

Galleggia il genitore.

  <div style="float: left;">
        <div style="float: left;">Div 1</div>
        <div style="float: left;">Div 2</div>
    </div>

Pro : codice semantico.
Contro : non si può sempre volere il genitore fluttuante. Anche se lo fai, fai galleggiare il genitore dei genitori, e così via? Devi far galleggiare ogni elemento ancestrale?

Soluzione 2

Dare al genitore un'altezza esplicita.

    <div style="height: 300px;">
        <div style="float: left;">Div 1</div>
        <div style="float: left;">Div 2</div>        
    </div>

Pro : codice semantico.
Contro : Non flessibile: se il contenuto cambia o il browser viene ridimensionato, il layout si interromperà.

Soluzione 3

Aggiungi un elemento "spacer" all'interno dell'elemento genitore, in questo modo:

    <div>
        <div style="float: left;">Div 1</div>
        <div style="float: left;">Div 2</div>
        <div class="spacer" style="clear: both;"></div>
    </div>

Pro : semplice da codificare.
Contro : non semantico; il div spacer esiste solo come un hack del layout.

Soluzione 4

Imposta genitore su overflow: auto .

   <div style="overflow: auto;">
        <div style="float: left;">Div 1</div>
        <div style="float: left;">Div 2</div>        
    </div>

Pro : non richiede div extra.
Contro : Sembra un trucco - non è lo scopo dichiarato della proprietà di overflow .

Commenti? Altri suggerimenti?


Soluzione 1:

Il metodo più affidabile e discreto sembra essere questo:

Demo: http://jsfiddle.net/SO_AMK/wXaEH/

HTML:

<div class="clearfix">
    <div style="float: left;">Div 1</div>
    <div style="float: left;">Div 2</div>
</div>​

CSS:

.clearfix::after { 
   content: " ";
   display: block; 
   height: 0; 
   clear: both;
}

Con un po 'di targeting CSS non hai nemmeno bisogno di aggiungere una classe al DIV padre.

Questa soluzione è retrocompatibile con IE8, quindi non devi preoccuparti che i vecchi browser non funzionino.

Soluzione 2:

Un adattamento sulla soluzione 1 è stato suggerito ed è il seguente:

Demo: http://jsfiddle.net/wXaEH/162/

HTML:

<div class="clearfix">
    <div style="float: left;">Div 1</div>
    <div style="float: left;">Div 2</div>
</div>​

CSS:

.clearfix::after { 
   content: " ";
   display: block; 
   height: 0; 
   clear: both;
   *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML += '<div class="ie7-clear"></div>' );
}

.ie7-clear {
    display: block;
    clear: both;
}

Questa soluzione sembra essere retrocompatibile con IE5.5 ma non è stata testata.

Soluzione 3:

È anche possibile impostare la display: inline-block; e width: 100%; emulare un normale elemento di blocco mentre non crolla.

Demo: http://jsfiddle.net/SO_AMK/ae5ey/

CSS:

.clearfix {
    display: inline-block;
    width: 100%;
}

Questa soluzione dovrebbe essere retrocompatibile con IE5.5, ma è stata testata solo in IE6.


Anche se il codice non è perfettamente semantico, penso che sia più semplice avere quello che io chiamo un "clearing div" nella parte inferiore di ogni contenitore con galleggianti in esso. Infatti, ho incluso la seguente regola di stile nel mio blocco di reset per ogni progetto:

.clear 
{
   clear: both;
}

Se stai pensando a IE6 (dio ti aiuti), potresti dare a questa regola anche un'altezza e un'altezza della linea 0px.


Di solito uso l' overflow: auto trucco overflow: auto ; anche se questo non è, in senso stretto, l'uso previsto per l'overflow, è un po 'correlato - abbastanza per renderlo facile da ricordare, certamente. Il significato di float: left stesso è stato esteso per vari usi in modo più significativo rispetto a overflow in questo esempio, IMO.


Esistono diverse versioni del clearfix, con Nicolas Gallagher e Thierry Koblentz come autori chiave.

Se vuoi supporto per i browser più vecchi, è meglio usare questo clearfix:

.clearfix:before, .clearfix:after {
    content: "";
    display: table;
}

.clearfix:after {
    clear: both;
}

.clearfix {
    *zoom: 1;
}

In SCSS, dovresti usare la seguente tecnica:

%clearfix {
  &:before, &:after {
    content:" ";
    display:table;
  }

  &:after {
    clear:both;
  }

  & {
    *zoom:1;
  }
}

#clearfixedelement {
    @extend %clearfix;
}

Se non ti interessa il supporto per i browser più vecchi, c'è una versione più breve:

.clearfix:after {
    content:"";
    display:table;
    clear:both;
}

Il problema principale che si può riscontrare cambiando l'overflow in auto o hidden è che tutto può diventare scorrevole con il tasto centrale del mouse e un utente può rovinare l'intero layout del sito.


Il problema si verifica quando un elemento fluttuante si trova all'interno di una casella contenitore, quell'elemento non forza automaticamente la regolazione dell'altezza del contenitore all'elemento flottato. Quando un elemento è flottato, il suo genitore non lo contiene più perché il float viene rimosso dal flusso. Puoi utilizzare 2 metodi per risolverlo:

  • { clear: both; }
  • clearfix

Una volta compreso ciò che accade, utilizzare il metodo seguente per "cancellarlo".

.clearfix:after {
    content: ".";
    display: block;
    clear: both;
    visibility: hidden;
    line-height: 0;
    height: 0;
}

.clearfix {
    display: inline-block;
}

html[xmlns] .clearfix {
    display: block;
}

* html .clearfix {
    height: 1%;
}

Dimostrazione :)


La soluzione ideale sarebbe utilizzare il inline-block per le colonne anziché il floating. Penso che il supporto del browser sia abbastanza buono se segui (a) applica il inline-block solo agli elementi che sono normalmente in linea (ad esempio span ); e (b) aggiungi -moz-inline-box per Firefox.

Controlla anche la tua pagina in FF2 perché ho avuto un sacco di problemi durante l'annidamento di alcuni elementi (sorprendentemente, questo è l'unico caso in cui IE funziona molto meglio di FF).


Piuttosto che mettere overflow:auto sul genitore, mettere overflow:hidden

Il primo CSS che scrivo per qualsiasi pagina web è sempre:

div {
  overflow:hidden;
}

Allora non dovrò mai preoccuparmene.


Un'altra possibile soluzione che ritengo sia più semanticamente corretta è quella di cambiare gli elementi interni flottati per essere 'display: inline'. Questo esempio e quello su cui stavo lavorando quando ho trovato questa pagina usano entrambi i flo float esattamente nello stesso modo in cui sarebbe usata una span. Invece di usare div, passa a span, o se stai usando un altro elemento che è di default 'display: block' invece di 'display: inline', quindi cambiala in 'display: inline'. Credo che questa sia la soluzione al 100% semanticamente corretta.

La soluzione 1, che fa galleggiare il genitore, è essenzialmente quella di cambiare l'intero documento da flottare.

La soluzione 2, impostando un'altezza esplicita, è come disegnare una scatola e dire che voglio mettere una foto qui, cioè usarla se stai facendo un tag img.

La soluzione 3, aggiungendo un distanziatore per cancellare il float, è come aggiungere una linea in più al di sotto del contenuto e fare confusione con gli elementi circostanti. Se usi questo approccio, probabilmente vorrai impostare il div in altezza: 0px.

Soluzione 4, overflow: auto, sta riconoscendo che non si sa come disporre il documento e si ammette che non si sa cosa fare.


Una delle soluzioni più conosciute è una variante della soluzione numero 3 che utilizza uno pseudo elemento invece di un elemento html non semantico.

Va qualcosa come questo ...

.cf:after {
    content: " ";
    display: block;
    visibility: hidden;
    height: 0;
    clear: both;
}

Lo inserisci nel tuo foglio di stile e tutto ciò che ti serve è aggiungere la classe 'cf' all'elemento che contiene i float.

Quello che uso è un'altra variazione che viene da Nicolas Gallagher.

Fa la stessa cosa, ma è più breve, sembra più ordinata, e forse è usata per realizzare un'altra cosa che è piuttosto utile - impedire che i margini degli elementi secondari possano crollare con i suoi genitori '(ma per questo hai bisogno di qualcos'altro - leggi di più a riguardo qui http://nicolasgallagher.com/micro-clearfix-hack/ ).

.cf:after {
    content: " ";
    display: table;
    clear: float;
}





clearfix