It is necessary to arrange the blocks in the form of chat, as in the picture. Please help me, what am I doing wrong and how to do it more correctly, cleaner?

.text-align-center { text-align: center; } .item:nth-child(even) { direction: rtl; } .item { position: relative; margin: auto; white-space: nowrap; } div { display: block; } .person { display: inline-block; overflow: hidden; position: relative; vertical-align: middle; } .text { display: inline-block; vertical-align: middle; font-size: 30px; direction: ltr; } .all-chat { width: 500px; } 
 <!DOCTYPE html> <html> <head> <title>homework 5</title> <meta charset="utf-8"> <link rel="stylesheet" type="text/css" href="hw.css"> </head> <body> <h1 class="text-align-center">Chat</h1> <div class="all-chat"> <div class="item"> <div class="person"> <img src="http://placekitten.com/40/50" alt="photo" class="image"> <div class="text"> <div class="data">9:03</div> <div class="message">Hi</div> </div> </div> </div> <div class="item"> <div class="person"> <img src="http://placekitten.com/40/50" alt="photo" class="image"> <div class="text"> <div class="data">9:05</div> <div class="message">Hello!</div> </div> </div> </div> </div> </body> </html> 

enter image description here

  • 2
    .item: nth-child (even) { - and if you have several messages in a row from one user? Make just separate classes for the sent message and for the received message. It may even be worthwhile to make different markup in them - Grundy

3 answers 3

I give general tips and turn to the details of your code:

  1. When layout, be interested in the purpose of CSS properties. That is, the argument of use is simply because “this is how it works”, use it last (if everything else does not work).

    For example, you use the direction property. This property is intended to indicate the direction of the text. In most languages, the text is written from left to right ( ltr is the default), but Arabic and Hebrew text is written from right to left and the direction: rtl; indicated for this text direction: rtl; . It turns out that you are using this property for other purposes.

  2. Careful use absolute positioning. Ideally, use it only when it is necessary that the elements overlap others and the element is removed from the display stream. For example, modal windows, drop-down lists with a more complex display than standard select , etc. Also used for some recipes such as placing an icon inside a text field. But in this case I do not see the need for absolute positioning.

  3. Use pseudo-selectors with great care (for example, first-child; only-child , nth-child , etc.). Because pseudo-selectors

    • ignore visible block or not. That is, if you hide one of the blocks using display: none , it will still be taken into account when applying a pseudo-selector.
    • when applying, take into account only the sequence number of the element relative to the parent. That is, the .item:nth-child(even) pseudo- .item:nth-child(even) works like this: “select every even child who has an item class”, and not so “select every even element with an item class”. Illustrating by example:

       .item:nth-child(even) { background-color: red; } 
       <div class="container"> <div class="not-item"> One (not item) </div> <div class="item"> Two (item) </div> <div class="item"> Three (item) </div> <div class="not-item"> Four (not item) </div> <div class="item"> Five (item) </div> <div class="item"> Six (item) </div> </div> 

    If you add elements next to .item , the layout may break.

    Therefore, I recommend to look, it may be worth asking separate classes for special types of elements.


In this case, I also believe that chat means that there can be several messages from one user in a row. Therefore, applying styles only to even elements seems to be incorrect.

  1. Examine the flexbox. The arrangement of elements using float , clear , vertical-align does not have such power and is not as flexible and maintainable.

  2. Learn CSS methodology. BEM or SMACSS. So that you can easily change the layout, as well as if the same blocks or similar ones are needed on other pages, you would easily add and change them. In the example, I will use BEM.

  3. Do not use faceless or ambiguous names like .item . It could be anything. The use of this class depends on who is the parent and what is next. And this means that if a .item block is added .item , the same styles will be applied for it, which may be undesirable. Treat selectors as well as variables. They must have a strictly defined purpose and the name must clearly reflect it. If you call chat-item , for example, then the meaning of this block is clearer.

  4. Treat layout as programming, for which ease of perception, flexibility and maintainability are important. Also equally important is the compliance of standards. Layout spoil duplication code, try to avoid them. The use of modern preprocessors with variables, cycles, conditions makes the layout almost indistinguishable from programming.


results

For each series of messages, I created a .chat-item block, where the avatar and one or more messages from the user will be located.

In order to apply styles to invert the layout (for the responding) column, I set the flex-direction: row-reverse; That inverts the order of the elements.

The BEM methodology is used here.
In order not to create additional classes for nested elements when inverting, I sacrificed the purity of BEM and added selectors with nesting ( .chat__item--responder .chat__message , .chat__item--responder .chat__message-content ). According to the methodology itself (ideally), only classes without nesting should be used.

As a result, the code might look like this:

 .chat__header { text-align: center; } .chat__item { display: flex; align-items: flex-start; } .chat__person-avatar { border-radius: 50%; } .chat__messages { margin-left: 10px; } .chat__message { display: flex; align-items: center; margin-right: 10px; } .chat__message-content { border-radius: 5px; padding: 7px; background-color: #ccc; display: inline-block; margin-left: 5px; } .chat__item--responder { flex-direction: row-reverse; } .chat__item--responder .chat__message { flex-direction: row-reverse; } .chat__item--responder .chat__message-content { margin-left: 0; margin-right: 5px; } 
 <div class="chat"> <h1 class="chat__header">Chat</h1> <div class="chat__content"> <div class="chat__item"> <img src="http://placekitten.com/40/50" alt="photo" class="chat__person-avatar"> <div class="chat__messages"> <div class="chat__message"> <div class="chat__message-time">9:03</div> <div class="chat__message-content">Hi</div> </div> <div class="chat__message"> <div class="chat__message-time">9:03</div> <div class="chat__message-content">How are you?</div> </div> </div> </div> <div class="chat__item chat__item--responder"> <img src="http://placekitten.com/40/50" alt="photo" class="chat__person-avatar"> <div class="chat__messages"> <div class="chat__message"> <div class="chat__message-time">9:05</div> <div class="chat__message-content">Hello</div> </div> <div class="chat__message"> <div class="chat__message-time">9:07</div> <div class="chat__message-content">I'm fine. Let's have a dinner today.</div> </div> <div class="chat__message"> <div class="chat__message-time">9:07</div> <div class="chat__message-content">What do you think about it? </div> </div> </div> </div> </div> 

    Pay attention to changing the order of elements with the help of order , otherwise everything is standard.

     * { margin: 0; padding: 0; box-sizing: border-box; } .chat { padding: 40px; } .message { width: 100%; display: flex; flex-wrap: wrap; align-items: center; } .message--user-1 + .message--user-2, .message--user-2 + .message--user-1 { margin-top: 1em; } .message--user-1 + .message--user-1, .message--user-2 + .message--user-2 { margin-top: .5em; } .message__time { font-size: 10px; color: #ccc; width: 100%; margin: 0 0 5px 50px; } .message__author-pic { margin: 0 10px 0 0; } .message__text { padding: 10px; border-radius: 10px; border: 1px solid #69b4f3; background-color: #bfe2ff; max-width: 70%; } .message--user-2 { justify-content: flex-end; } .message--user-2 .message__time { text-align: right; margin: 0 50px 5px 0; } .message--user-2 .message__author-pic { order: 1; margin: 0 0 0 10px; } .message--user-2 .message__text { background-color: #69b4f3; } 
     <section class="chat"> <div class="message message--user-1"> <time class="message__time">21.02.2017 21:12:07</time> <figure class="message__author-pic"> <img src="http://pipsum.com/40x40.jpg"> </figure> <div class="message__text"> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis at purus nibh. Cras metus nulla, vestibulum in auctor ac, fermentum vitae tellus.</p> </div> </div> <div class="message message--user-2"> <time class="message__time">21.02.2017 21:12:07</time> <figure class="message__author-pic"> <img src="https://placeimg.com/40/40/people"> </figure> <div class="message__text"> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis at purus nibh. Cras metus nulla, vestibulum in auctor ac, fermentum vitae tellus.</p> </div> </div> <div class="message message--user-2"> <time class="message__time">21.02.2017 21:12:07</time> <figure class="message__author-pic"> <img src="https://placeimg.com/40/40/people"> </figure> <div class="message__text"> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis at purus nibh. Cras metus nulla, vestibulum in auctor ac, fermentum vitae tellus.</p> </div> </div> <div class="message message--user-1"> <time class="message__time">21.02.2017 21:12:07</time> <figure class="message__author-pic"> <img src="http://pipsum.com/40x40.jpg"> </figure> <div class="message__text"> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis at purus nibh. Cras metus nulla, vestibulum in auctor ac, fermentum vitae tellus.</p> </div> </div> </section> 

      For example, I did this, though not the best option. But I advise you to use some frameworks for such ploys.

       .text-align-center { text-align: center; } .item:nth-child(even) { direction: rtl; } .item { position: absolute; margin: auto; white-space: nowrap; } .item-2 { position: absolute; margin: auto; white-space: nowrap; right: 0; top: 200px; } div { display: block; } .person { display: inline-block; overflow: hidden; position: relative; vertical-align: middle; margin-right: 50px; /* Отступ справа */ margin-left: 50px; /* Отступ слева*/ } .text { display: inline-block; vertical-align: middle; font-size: 30px; direction: ltr; background: #cccccc; /* Цвет фона под заголовком */ color: black; /* Цвет текста */ padding: 2px; /* Поля вокруг текста */ } .all-chat { width: 500px; } .date{ background: #cccccc; /* Цвет фона под заголовком */ color: black; /* Цвет текста */ padding: 2px; /* Поля вокруг текста */ } 
       <!DOCTYPE html> <html> <head> <title>homework 5</title> <meta charset="utf-8"> <link rel="stylesheet" type="text/css" href="hw.css"> </head> <body> <h1 class="text-align-center">Chat</h1> <div class="all-chat"> <div class="item"> <div class="person"> <img src="http://placekitten.com/40/50" alt="photo" class="image"> <div class="text"> <div class="date">9:03</div> <div class="text">Hi</div> </div> </div> </div> <div class="item-2"> <div class="person"> <img src="http://placekitten.com/40/50" alt="photo" class="image-2"> <div class="text"> <div class="date">9:05</div> <div class="text">Hello!</div> </div> </div> </div> </div> </body> </html>