Как предотвратить изменение макетов CSS Flex / сетки на dir=»RTL»

#css #flexbox #grid #internationalization

Вопрос:

У меня есть простой div ( grid layout но то же самое относится и к flexbox ), который показывает три разных text элемента.

Проблема в том , что всякий раз, когда для моего html dir атрибута установлено значение rtl , порядок элементов сетки меняется, и я хотел бы иметь возможность предотвратить это изменение в этом конкретном случае (где порядок содержимого основан не на направлении записи, а на семантическом значении.

Для примера, вот как выглядят мои предметы:

 let direction = 'rtl';
document.getElementById('toggle-direction').addEventListener('click', () => {
  direction = direction === 'rtl' ? 'ltr' : 'rtl';

  document.documentElement.setAttribute('dir', direction);
}); 
 .container {
  display: grid;
  grid-template-rows: 1fr;
  grid-template-columns: repeat(3, 1fr);
  border-radius: 5px;
  padding: 10px;
}

.left-arrow {
  grid-column: 1 / 2;
  grid-row: 1 / 2;

  margin-inline-end: auto;
}

.center-content {
  grid-row: 1 / 2;
  grid-column: 2 / 3;
  text-align: center;
}

.right-arrow {
  grid-row: 1 / 2;
  grid-column: 3 / 4;

  margin-inline-start: auto;
  
}

#toggle-direction {
  grid-row: 2 / 3;
  grid-column: 1 / 4;
} 
 <div class="container">
  <span class="left-arrow"><</span>
  <span class="center-content">Center content</span>
  <span class="right-arrow">></span>
  <button id="toggle-direction">Toggle direction</button>
</div> 

PS: Я мог бы добавить direction: ltr; в .container селектор, но это создало бы нежелательный стиль, так как я хочу использовать встроенный стиль.

Комментарии:

1. укажите направление в сеточном контейнере, которое должно быть ltr

2. @TemaniAfif, я улучшил код, чтобы показать, почему простое добавление direction: ltr не является решением

Ответ №1:

Насколько я понимаю, вы хотите, чтобы стрелки сохраняли свою ориентацию. Поэтому вы должны изолировать и обернуть элементы, направление которых вы хотите согласовать, в контейнеры с согласованным направлением потока (и поместить все, что вы хотите обновить, за пределы этих контейнеров) примерно так :

 let direction = 'rtl';
document.getElementById('toggle-direction').addEventListener('click', () => {
  direction = direction === 'rtl' ? 'ltr' : 'rtl';

  document.documentElement.setAttribute('dir', direction);
}); 
 .container {
  display: grid;
  grid-template-rows: 1fr;
  grid-template-columns: repeat(3, 1fr);
}

.ltr {
  direction: ltr;
 }

.left-arrow {
  grid-column: 1 / 2;
  text-align: center;
}

.center-content {
  grid-column: 2 / 3;
  text-align: center;
}

.right-arrow {
  grid-column: 3 / 4;
  text-align: center;
}

#toggle-direction {
  grid-column: 1 / 4;
} 
 <!-- inherit direction flow --> 
<div class="container ltr">
  <!-- ltr direction flow --> 
  <p class="left-arrow">Left arrow</p>
  <p class="center-content">Center content</p>
  <p class="right-arrow">Right arrow</p>
</div>
<div class="container">
  <!-- inherit direction flow -->
  <button id="toggle-direction">Toggle direction</button>
</div> 

Внесенные изменения: заверните первую строку, которая была у вас внутри контейнера, в другой контейнер ( class="colum rtl" ), у которого всегда есть направление.
Небольшие обновления css для сохранения вида.

В качестве альтернативы вы можете поместить контейнер со стрелками внутри контейнера с помощью кнопки. Но для того, чтобы иметь согласованное rtl направление, вам нужно будет поместить их в контейнер (с class="rtl" ), и вам понадобится немного больше обновлений для вашего css, чтобы сохранить аспект.

В качестве альтернативы, если у вас действительно нет возможности изолировать все компоненты, необходимые для обеспечения согласованного направления, вы можете для некоторых конкретных случаев создать класс class="inherit-direction" (например), и в вашем js, когда вы меняете направление документа, измените направление контейнеров с помощью этого класса ( document.getElementsByClassName("inherit-direction") и повторите их).

Но я бы настоятельно посоветовал использовать этот последний вариант только в качестве последней меры и максимально ограничить количество применений.

Комментарии:

1. В этом и заключается проблема с таким упрощенным примером. Проблема в том, что теперь каждый дочерний компонент .container будет элементом, основанным на направлении ltr , и потеряет все соответствующие стили, предоставленные из dir="rtl" . Я улучшу свой пример.

2. Лучшим способом было бы поместить компоненты, в которых вы хотите обеспечить согласованный поток, в отдельные контейнеры и добавить к ним универсальный класс . Таким образом, все, что находится снаружи, наследует тело, и только то, что находится внутри этих контейнеров, остается ltr (я обновлю пример для лучшего понимания).

3. Я обновил ответ. Надеюсь, это поможет 🙂