Помогите сверстать чат

320
13 января 2017, 07:35

Нужно расположить блоки в виде чата, как на картинке. Помогите, пожалуйста, что я делаю не так и как это сделать правильнее, чище? Спасибо!

.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>

Answer 1

Даю общие советы и перехожу к деталями вашего кода:

  1. При вёрстке интересуйтесь предназначением CSS-свойств. То есть довод использования — просто потому что "так работает" используйте в последнюю очередь (если всё остальное не работает).

    К примеру, вы используете свойство direction. Это свойство предназначено для указания направления текста. В большинстве языков текст пишется слева направо (значение ltr по умолчанию), но на арабском и иврите текст пишется справа налево и для этого текста указывается direction: rtl;. Получается, что вы используете это свойство не по назначению.

  2. Осмотрительней используйте абсолютное позиционирование. В идеале его использовать только когда нужно чтобы элементы перекрывали другие и элемент извлёкся из потока отображения. К примеру, модальные окна, выпадающие списки с более сложным отображением, чем стандартный select и т.д. Также используется для в некоторых рецептах вроде поместить иконку внутри текстового поля. Но в данном случае не вижу в потребности в абсолютном позиционировании.

  3. С большой осторожностью используйте псевдоселекторы (к примеру, first-child;, only-child, nth-child и т.д.). Потому что псевдоселекторы

    • игнорируют видимый блок или нет. То есть если вы скроете один из блоков с помощью display: none, он всё равно будет учитываться при применении псевдоселектора.
    • при применении учитывают лишь порядковый номер элемента относительно родителя. То есть псевдоселектор .item:nth-child(even) работате так "выбрать каждого чётного ребёнка, у которого есть класс item", а не так "выбрать каждый чётный элемент с классом item". Иллюстрирую примером:

.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>

Если вы добавите элементы рядом с .item, вёрстка может сломаться.

Поэтому рекомендую посмотреть, может стоит задавать отдельные классы для особых типов элементов.

В данном случае, я полагаю также, что чат означает, что может быть несколько сообщений подряд от одного пользователя. Поэтому применение стилей только к чётным элементам, кажется неверным.

  1. Изучите flexbox. Расположение элементов с помощью float, clear, vertical-align не обладает такой мощью и не такое гибкое и сопровождаемое.

  2. Изучите CSS-методологию. BEM или SMACSS. Для того, чтобы вы могли легко менять вёрстку, а также если такие же блоки или подобные нужны на других страницах вы бы их без проблем добавляли и меняли. В примере, я буду использовать BEM.

  3. Не используйте безликие или неоднозначные имена вроде .item. Это же может быть что угодно. Применение этого класса зависит от того, кто в нём родитель и что рядом находится. А это значит, что если где-то добавится блок .item, то те же стили для него и применятся, что, возможно, будет нежелательно. Относитесь к селекторам также как к переменным. У них должно быть строго определённое предназначение. Если вы назовёте, к примеру, chat-item, то уже более ясно значение этого блока.

  4. Относитесь к вёрстке как к программированию, для которого важна легкость восприятия, гибкость и сопровождаемость. Также не менее важно соответствие стандартов. Вёрстку портят дублирования кода, старайтесь их избегать. Использование современных препроцессоров с переменными, циклами, условиями делает вёрстку почти неотличимой от программирования.

Результаты

Для каждой серии сообщений создал блок .chat-item, где будет находиться аватар и одно или несколько сообщений от пользователя.

Для того, чтобы применять стили для инвертирования расположение (для отвечающего) колонки я задал flex-direction: row-reverse;, что инвертирует порядок расположения элементов.

Здесь использована методология BEM.
Для того, чтобы не создавать дополнительные классы для вложенных элементов при инвертировании я пожертвовал чистотой BEM и добавил селекторы с вложенностью (.chat__item--responder .chat__message, .chat__item--responder .chat__message-content). По самой методологии (в идеале) следует использовать только классы без вложенности.

В результате код может выглядеть так:

.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>

Answer 2

Обратите внимание на изменение порядка элементов при помощи order, в остальном — всё стандартно.

* { 
  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>

Answer 3

Я к примеру сделал так, правда не самый лучший вариант. Но советую воспользоваться каким-нибудь фреймворков для таких затей.

.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>

READ ALSO
C# - чтение данных с HID-клавиатуры

C# - чтение данных с HID-клавиатуры

Имеется HID-клавиатура (на пульте ДУ)Требуется определять, какие HID-коды она посылает на USB-порт

362
Изменение текста [требует правки]

Изменение текста [требует правки]

Подскажите как поменять текст при нажатий на кнопку в Unity3d? Я создал картинку и на ней текст

306
установка ComboBoxItem в качестве SelectedItem у ComboBox

установка ComboBoxItem в качестве SelectedItem у ComboBox

Не срабатывает свойство IsSelected у ComboBoxItemВ чем причина?

489
Почему не изменяется свойство контрола?

Почему не изменяется свойство контрола?

У меня есть четыре TextBox и один ComboBoxВ зависимости от выбранного элемента в ComboBox, нужно включить/выключить (Enabled) TextBox

366