2015-11-04 9 views
5

Sembra che dovrebbe essere possibile con la flexbox, ma non riesco a capirlo.Può Flexbox? Finestra di chat con input in basso, chat a scorrimento

http://codepen.io/MichaelJCole/pen/NGBVGe

Obiettivi:

  1. textarea (per typeing nei messaggi) rimane in fondo tutto il tempo.
  2. le chat iniziano nella parte inferiore, quindi eseguono lo scorrimento verso l'alto in base alle esigenze.
  3. Se si utilizza "Google Hangouts", come l'app messaggio in questo.

Ecco il markup:

<div id="chatBar"> 
    <div id="chatList"> 
     <div class="chat mine">hello world</div> 
     <div class="chat theirs">hello moon</div> 
    </div> 
    <input id="chatBarInput" class="form-control" type="textarea"> 
    </div> 

Ed ecco il CSS:

html, body { height: 100%; } 
#chatBar { 
    height: 100%; 
    display: flex; 
    flex-flow: column nowrap; 
    justify-content: flex-end; 
    overflow: none; 
} 

#chatList { 
    flex: 0 1 auto; 
    display: flex; 
    flex-flow: column nowrap; 
    justify-content: flex-end; 
    overflow-y: scroll; 
} 

#chatBarInput { 
    flex: 1 0 auto; 
} 

.chat { 
    flex: none; 
    align-self: flex-start; 
    background-color: lightgreen; 
} 

.chat.mine { 
    align-self: flex-end; 
    background-color: pink; 
} 

non riesco a ottenere #chatBar a "spremere" #chatList senza impostare un'altezza. Che cosa stavo cercando di evitare usando flexbox: -/

Spiacente, sono un codificatore backend. Ho provato un sacco di roba, poi l'ho ridotta per il CodePen.

Sembra che dovrei essere in grado di dire al Flexbox interno di scorrere, lasciando solo l'esterno. Devo usare la posizione: assoluta?

+0

Non sono del tutto certo cosa stai cercando di realizzare. Ma vedo che stai usando 'height: 100%' nel tuo contenitore flex ('# chatBar'). * 100% di cosa? * È necessario fornire una cornice di riferimento quando si utilizzano altezze percentuali in CSS. Aggiungi questo al tuo codice: 'html, body {height: 100%; } ' –

+0

Ok, buon punto. L'ho aggiunto alla codepen, ma ho ancora lo stesso problema. Quando il corpo è piccolo, l'input scorre verso il basso. Voglio che il flexbox esterno inserisca l'input * in * in basso e non scorra mai. La flexbox interna dovrebbe posizionare gli oggetti nella parte inferiore e scorrere se si rovesciano. Questo aiuta? –

risposta

10

Non riesco a #chatBar a "spremere" #chatList senza impostare un'altezza. Che è quello che stavo cercando di evitare utilizzando FlexBox

hai avuto il flex-basis insieme a auto per tutti gli elementi. Senza altezza esplicita, il modello di flex cercherà automaticamente di sistemare tutto all'interno dello spazio disponibile riducendo o espandendo gli elementi. Questo è il motivo per cui non si è in grado di far funzionare il #chatList come previsto. Lo stesso div e le singole chat si espandono o si restringono all'interno dello spazio disponibile.

Che cosa si dovrebbe fare è quello di iniziare semplice:

#chatBar { 
    height: 100%; overflow: hidden; 
    display: flex; flex-flow: column; 
} 
#chatList { 
    /* grow or shrink as required from flex-basis height of 20% */ 
    flex: 1 1 20%; 
    display: flex; flex-direction: column; 
    overflow: auto; 
} 

/* do not grow or shrink with a flex-basis height of 80% */ 
#chatBarInput { flex: 0 0 80%; } 

e sarete in grado di vedere che funziona. Potresti quindi portarlo più lontano da qui.

tuo codepen modificata: http://codepen.io/Abhitalks/pen/ZbjNvQ/


Obiettivi:

  1. textarea (per typeing nei messaggi) rimane in fondo tutto il tempo.
  2. le chat iniziano nella parte inferiore, quindi eseguono lo scorrimento verso l'alto in base alle esigenze.
  3. Se si utilizza "Google Hangouts", come l'app messaggio in questo.

Il trucco sarebbe quello di utilizzare flex-direction: column-reverse e anteporre i nuovi messaggi al contenitore invece di aggiungere quelli.

Ho preso una mia vecchia risposta e ho cambiato il layout in flex-model per una dimostrazione di questo scopo. Puoi leggere il codice per vedere come è fatto.

Demo Fiddle: http://jsfiddle.net/abhitalks/khj4903t/

Demo Snippet:

var btn \t = document.getElementById('btn'), 
 
    inp \t = document.getElementById('inp'), 
 
    chats \t = document.getElementById('chatWindow') 
 
; 
 
btn.addEventListener('click', postMsg); 
 

 
inp.addEventListener('keyup', function(e) { 
 
\t if (e.keyCode == 13) { postMsg(); } 
 
}); 
 

 
function postMsg() { 
 
\t var msg \t = inp.value, 
 
     bubble \t = document.createElement('div'), 
 
     p \t \t = document.createElement('p'); 
 
    if (msg.trim().length <= 0) { return; } 
 
    bubble.classList.add('bubble'); 
 
    bubble.classList.add('right'); 
 
    p.textContent = msg; 
 
    bubble.appendChild(p); 
 
    inp.value = ''; 
 
    chats.insertBefore(bubble, chats.firstChild); 
 
}
* { box-sizing: border-box; margin: 0; padding: 0; } 
 
html, body { height: 100%; overflow: hidden; } 
 
.wrap { 
 
    margin: 8px; height: 90%; width: 50%; 
 
    display: flex; flex-direction: column; 
 
} 
 
.container { 
 
    flex: 1 1 90%; display: flex; flex-direction: column; 
 
    background-color: #eee; border: 1px solid #ccc; overflow: auto; 
 
} 
 
.form { flex: 0 0 32px; display: flex; border: 1px solid #ddd; } 
 
.form > input[type=text] { flex: 1 1 auto; border: 1px solid #eee; } 
 
.form > input[type=button] { flex: 0 0 20%; border: 1px solid #eee; } 
 
.bubble { flex: 1 1 auto; clear: both; } /* clear the floats here on parent */ 
 
.bubble p { 
 
    border-radius: 5px; 
 
    padding: 8px; margin: 8px 12px; 
 
    max-width: 80%; /* this will make it not exceed 80% and then wrap */ 
 
    position: relative; transition: background-color 0.5s; 
 
} 
 
.left p { background-color: #ccc; float: left; } /* floated left */ 
 
.right p { background-color: #33c; color: #fff; float: right; } /* floated right */ 
 
/* classes below are only for arrows, not relevant */ 
 
.left p::before { 
 
    content: ''; position: absolute; 
 
    width: 0; height: 0; left: -8px; top: 8px; 
 
    border-top: 4px solid transparent; 
 
    border-right: 8px solid #ccc; 
 
    border-bottom: 4px solid transparent; 
 
} 
 
.right p::after { 
 
    content: ''; position: absolute; 
 
    width: 0; height: 0; right: -8px; bottom: 8px; 
 
    border-top: 4px solid transparent; 
 
    border-left: 8px solid #33c; 
 
    border-bottom: 4px solid transparent; 
 
}
<div class="wrap"> 
 
    <div id="chatWindow" class="container"> 
 
     <div class="bubble left"><p>msg</p></div> 
 
     <div class="bubble left"><p>long message</p></div> 
 
     <div class="bubble right"><p>ultra long message which can wrap at eighty percent </p></div> 
 
     <div class="bubble left"><p>lorem ipsum</p></div> 
 
     <div class="bubble right"><p>very long message</p></div>  
 
     <div class="bubble right"><p>one more message</p></div>  
 
     <div class="bubble left"><p>lorem ipsum</p></div> 
 
     <div class="bubble right"><p>another message</p></div>  
 
     <div class="bubble left"><p>lorem ipsum</p></div> 
 
     <div class="bubble right"><p>yet another message</p></div>  
 
     <div class="bubble left"><p>lorem ipsum</p></div> 
 
    </div> 
 
    <div id="inputWindow" class="form"> 
 
     <input id="inp" type="text" /> 
 
     <input id="btn" type="button" value="Send" /> 
 
    </div> 
 
</div>

+1

Questo è incredibilmente utile Abhitalks. Grazie! –

1

La barra di scorrimento verticale sul browser esiste perché hai impostato un height: 100% al body, e il user agent stylesheet applica a predefinito margin a body, in genere 8 pixel tutto intorno. Quindi, 100% + 16px avvia lo scorrimento verticale.

Aggiungi questo alla tua CSS: body { margin: 0; }

Per applicare la barra di scorrimento al FlexBox interno (.chatlist), qui ci sono due regolazioni:

#chatList { 
    flex: 0 1 75px; /* specify a height */ 
    display: flex; 
    flex-flow: column nowrap; 
    /* justify-content: flex-end; REMOVE */ 
    overflow-y: scroll; 
} 

DEMO: http://jsfiddle.net/5p2vy31p/1/