Логические свойства

Логические свойства CSS используют модель block/inline вместо top/right/bottom/left, автоматически адаптируясь к направлению текста (LTR/RTL) и режиму письма (горизонтальный/вертикальный).

Зачем нужно

Физические свойства (margin-left, padding-top) привязаны к физическим сторонам экрана. Логические свойства (margin-inline-start, padding-block) привязаны к направлению контента. Это критично для интернационализации (арабский, иврит — RTL) и вертикальных языков (японский, китайский).

Где используется

  • Многоязычные сайты (LTR + RTL)
  • Компоненты дизайн-систем (переиспользование в разных языках)
  • Современная замена физическим свойствам
  • Вертикальные раскладки (writing-mode: vertical)

Предпосылки

Модель block / inline

Горизонтальный режим (LTR):

            inline-start ───────→ inline-end
          ┌──────────────────────────────┐
 block    │                              │
 start    │         Контент              │
  │       │                              │
  ↓       │                              │
 block    └──────────────────────────────┘
  end

Горизонтальный режим (RTL):

            inline-end ←─────── inline-start
          ┌──────────────────────────────┐
 block    │                              │
 start    │                    محتوى     │
  │       │                              │
  ↓       └──────────────────────────────┘
 block
  end
  • block = направление потока блоков (обычно вертикальное: сверху вниз)
  • inline = направление текста (горизонтальное: LTR или RTL)

Маппинг свойств

Margin

Физическое Логическое В LTR
margin-top margin-block-start top
margin-bottom margin-block-end bottom
margin-left margin-inline-start left
margin-right margin-inline-end right
.element {
  /* Сокращения */
  margin-block: 20px;          /* top + bottom */
  margin-inline: 16px;         /* left + right (LTR) */
  margin-block: 10px 30px;     /* top: 10px, bottom: 30px */
  margin-inline: auto;         /* центрирование */
}

Padding

.card {
  padding-block: 20px;
  padding-inline: 24px;

  /* Или отдельно */
  padding-block-start: 16px;
  padding-block-end: 24px;
  padding-inline-start: 20px;
  padding-inline-end: 20px;
}

Border

.element {
  border-block: 1px solid #ddd;     /* top + bottom */
  border-inline-start: 4px solid blue; /* left в LTR, right в RTL */
  border-block-end: 2px solid #333;

  /* Радиус — тоже логический */
  border-start-start-radius: 8px; /* top-left в LTR */
  border-start-end-radius: 8px;   /* top-right в LTR */
  border-end-start-radius: 8px;   /* bottom-left в LTR */
  border-end-end-radius: 8px;     /* bottom-right в LTR */
}

Размеры

Физическое Логическое
width inline-size
height block-size
min-width min-inline-size
max-width max-inline-size
min-height min-block-size
max-height max-block-size
.container {
  inline-size: 100%;
  max-inline-size: 1200px;
  min-block-size: 100dvh;
  margin-inline: auto;
}

Позиционирование

Физическое Логическое
top inset-block-start
bottom inset-block-end
left inset-inline-start
right inset-inline-end
.dropdown {
  position: absolute;
  inset-block-start: 100%; /* top: 100% */
  inset-inline-start: 0;   /* left: 0 в LTR, right: 0 в RTL */
}

/* Сокращение inset */
.modal-overlay {
  position: fixed;
  inset: 0; /* top: 0; right: 0; bottom: 0; left: 0 */
}

Float и text-align

.image {
  float: inline-start; /* float: left в LTR, float: right в RTL */
  margin-inline-end: 16px;
}

.heading {
  text-align: start; /* left в LTR, right в RTL */
}

.price {
  text-align: end; /* right в LTR, left в RTL */
}

Overflow

.container {
  overflow-block: auto;   /* overflow-y */
  overflow-inline: hidden; /* overflow-x */
}

Практический пример: RTL-совместимый компонент

.notification {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-block: 12px;
  padding-inline: 16px;
  border-inline-start: 4px solid #007bff;
  border-radius: 0;
  border-start-end-radius: 8px;
  border-end-end-radius: 8px;
  background: #f0f7ff;
}

.notification-icon {
  flex-shrink: 0;
  inline-size: 24px;
  block-size: 24px;
}

.notification-close {
  margin-inline-start: auto;
  cursor: pointer;
}

В LTR: синяя полоска слева, крестик справа. В RTL: синяя полоска справа, крестик слева. Без единой строки дополнительного CSS.

Постепенная миграция

/* Можно мигрировать постепенно */
.card {
  /* Старое */
  /* padding: 20px 24px; */
  /* margin-bottom: 16px; */

  /* Новое */
  padding-block: 20px;
  padding-inline: 24px;
  margin-block-end: 16px;
}

Частые ошибки

  1. Смешивание физических и логических — неконсистентно:
    /* ПЛОХО */
    .element {
      margin-inline: 16px;
      padding-top: 20px; /* Физическое рядом с логическим */
    }
    /* ХОРОШО — всё логическое */
    .element {
      margin-inline: 16px;
      padding-block-start: 20px;
    }
    
  2. border-radius — сложный маппингborder-start-start-radius не интуитивен, проверяйте
  3. Забыли про vertical writing-mode — в вертикальном режиме block и inline меняются местами
  4. insetmargin shorthandinset: 10px 20px = top: 10px; right: 20px; bottom: 10px; left: 20px

Практика

  • Переписать компонент с физическими свойствами на логические
  • Добавить dir="rtl" к HTML и убедиться, что layout корректен
  • Использовать margin-inline: auto вместо margin: 0 auto
  • Попробовать inset: 0 для fullscreen overlay
  • Заменить text-align: left на text-align: start

Связанные темы

Ресурсы