4

From the title, one would assume that this might be a broad question, but it's actually based on 3 specific problems that I'm having in an attempt to replicate the upward-flowing, staggered format of a typical SMS conversation.

enter image description here

How can the common text message format be replicated purely with CSS?

Consider the following code:

<div id="messages" class="bordered shadowed">
    <div class="message from">Hey</div>
    <div class="message to">Sup</div>
    <div class="message from">How are ya?</div>
</div>

1. I can stagger the messages (.to anchored at the right and .from anchored at the left) by applying float:left/right but this leads to a problem:

The second time a .to is appended to #messages, unless it is a long message, it will be placed right beside the previous one, not below, because that's how float works.

2. Well, I tried to remedy this by placing each .message into a .messageWrapper and applying width:100% to the wrapper, but this leads to another problem:

.messages (which have float:left/right) don't fill the .messageWrapper, properly, and from there it gets a bit confusing.

3. Finally, I'm at a loss for how I might apply a solution to those problems in a way that will also let me anchor the elements to the bottom of the container as they should be, so that they flow upward.


Example:

I have a rather nice looking example, meaning there's a bulky bit of css, so I've minified to go on one line, avoiding a big code block here. If you'd like to view / edit it, simply click "edit the above snippet" and hit tidy.

div,input{box-sizing:border-box}:focus{outline-color:transparent;outline-style:none}::selection{background:#00a9ff}body{padding:0;margin:0;background-color:#0090d8}.float{float:left}.bordered{border-style:solid;border-width:1px}.shadowed{box-shadow:rgba(0,0,0,.1) 0 0 30px -10px inset,rgba(0,0,0,.5) 0 0 8px -5px inset}#messenger{width:50vw;height:100vh;background-color:#dbdbdb;font-family:Arial;border-width:0 10px;border-color:#26c8ff;margin-left:50px;box-shadow:rgba(38,200,255,.8) 0 0 300px -50px,rgba(38,200,255,.8) 0 0 10px -2px}#messages{color:#dbdbdb;width:100%;height:50%;background-color:#fff;padding:10px}#guesses{width:100%;height:40px}.guess{color:#efefef;font-size:24px;width:33.3333333%;height:100%;box-shadow:rgba(255,255,255,.2) 0 0 50px 10px inset;text-align:center;padding-top:5px;transition:box-shadow .3s,color .2s}.guess:hover{box-shadow:rgba(255,255,255,1) 0 0 120px -20px inset;color:#fff;cursor:pointer}#input{width:80%;height:30px;text-align:center;cursor:pointer;font-size:17px}#send{border-color:#212121;color:#fff;width:20%;background-color:#3f3f3f;height:30px;text-align:center;padding-top:5px;font-size:17px;box-shadow:rgba(255,255,255,.2) 0 0 50px 10px inset;transition:box-shadow .3s,color .2s}#send:hover{box-shadow:rgba(0,0,0,.3) 0 0 20px 0 inset;color:#fff;cursor:pointer}.message{padding:5px 10px;border-radius:100px;margin-top:50px;color:#fff}.to{float:right;background-color:#26c8ff;border-color:#00a2d8}.from{float:left;background-color:#0090d8;border-color:#005f8e}
<div id="messenger" class="bordered">
    <div id="messages" class="bordered shadowed">
        <div class="message from bordered">Hey</div>
        <div class="message to bordered">Sup</div>
        <div class="message from bordered">How are ya?</div>
    </div>
    <input type="text" id="input" class="float" placeholder="Message"></input>
    <div id="send" class="bordered float">Send</div>
    <div id="guesses">
        <div class="guess bordered float" id="guess-1">A</div>
        <div class="guess bordered float" id="guess-2">No</div>
        <div class="guess bordered float" id="guess-3">Bet</div>
    </div>
</div>

LIVE DEMO: http://jsfiddle.net/fr6ur53s/

2
  • Perhaps a comment as to why the down-vote? This is a 3 part question, but the 3 issues are inseparable parts of the same problem. I'm unsure how I could better ask this question. Commented Feb 11, 2015 at 2:35
  • Apply clear:both; to both the .to and .from css classes and replace the margin-top on .message css class with margin-bottom: 4px; or similar, to give some margin between consecutive to or from messages Commented Feb 11, 2015 at 2:41

1 Answer 1

3

You can clear:both each message, it will do the effect you want.
I also changed the .message margin to margin:10px 0;

Update: to fix your problem #3. I changed the class #messages. Using display: table-cell; and vertical-align: bottom, will do what you are looking aligning the content to the bottom.

Update: using dynamic width I wrapped the #messages with #messages-container using display:table; that way you can use width: 100%;

To understand how this work. The display:table-cell makes the div to behave like a td. Because the td is inside a table, you have to replicate the same behavior with divs. So, wrap that div with a container that has display:table to make the div behaves like a table. Then you give the div width: 100%. If you don't do that, the div (td) width with not expand 100%.

div,input{box-sizing:border-box}:focus{outline-color:transparent;outline-style:none}::selection{background:#00a9ff}body{padding:0;margin:0;background-color:#0090d8}.float{float:left}.bordered{border-style:solid;border-width:1px}.shadowed{box-shadow:rgba(0,0,0,.1) 0 0 30px -10px inset,rgba(0,0,0,.5) 0 0 8px -5px inset}#messenger{width:50vw;height:100vh;background-color:#dbdbdb;font-family:Arial;border-width:0 10px;border-color:#26c8ff;margin-left:50px;box-shadow:rgba(38,200,255,.8) 0 0 300px -50px,rgba(38,200,255,.8) 0 0 10px -2px}

#messages-container {
  display:table;
    width:100%;
}

#messages{
color:#dbdbdb;

width:100%;
height:50%;
background-color:#fff;
padding:10px;

 display: table-cell;
vertical-align: bottom;
}

#guesses{width:100%;height:40px}.guess{color:#efefef;font-size:24px;width:33.3333333%;height:100%;box-shadow:rgba(255,255,255,.2) 0 0 50px 10px inset;text-align:center;padding-top:5px;transition:box-shadow .3s,color .2s}.guess:hover{box-shadow:rgba(255,255,255,1) 0 0 120px -20px inset;color:#fff;cursor:pointer}#input{width:80%;height:30px;text-align:center;cursor:pointer;font-size:17px}#send{border-color:#212121;color:#fff;width:20%;background-color:#3f3f3f;height:30px;text-align:center;padding-top:5px;font-size:17px;box-shadow:rgba(255,255,255,.2) 0 0 50px 10px inset;transition:box-shadow .3s,color .2s}#send:hover{box-shadow:rgba(0,0,0,.3) 0 0 20px 0 inset;color:#fff;cursor:pointer}

.message{
color:#fff;
padding:5px 10px;
border-radius:100px;
margin:10px 0;
clear: both;
}

.to{float:right;background-color:#26c8ff;border-color:#00a2d8}

.from{float:left;background-color:#0090d8;border-color:#005f8e}
<div id="messenger" class="bordered">
  <div id="messages-container">
    <div id="messages" class="bordered shadowed">
        <div class="message from bordered">Hey</div>
          
        <div class="message to bordered">Sup</div>
          
        <div class="message from bordered">How are ya?</div>
    </div>
 </div>
  
    <input type="text" id="input" class="float" placeholder="Message"></input>
    <div id="send" class="bordered float">Send</div>
    <div id="guesses">
        <div class="guess bordered float" id="guess-1">A</div>
        <div class="guess bordered float" id="guess-2">No</div>
        <div class="guess bordered float" id="guess-3">Bet</div>
    </div>
</div>

Sign up to request clarification or add additional context in comments.

7 Comments

Thank you, and thanks @RussCam for the clear:both tip, very very neat, but this still leaves problem 3.
In order for #3 to work with pure CSS, it would have to float upward.
I considered that. I'm still doing some test and seeing if I can make it work with absolute positioning.
I almost accepted the answer until I saw I also had to change the width to 300px to make it work. Can it be done with a dynamic width?
That was a lazy solution. Check out the properly created solution.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.