Проблема с переходом CSS, абсолютным позиционированием и: target - PullRequest
2 голосов
/ 26 мая 2020

Я пытаюсь разработать одноэкранный, чистый css интерфейс веб-сайта, который позволяет пользователю выбирать из нескольких вариантов. Цель состоит в том, чтобы позволить пользователю самостоятельно выбрать свой путь к желаемому действию (регистрация, контактная форма, загрузка новой страницы и т. Д. c).

Мой подход заключался в том, чтобы поместить несколько абсолютно позиционированных div относительно позиционированная оболочка, затем используйте комбинацию z-index и: target для достижения желаемого результата.

Проблема, с которой я сталкиваюсь, - это переход между слайдами (каждый слайд отображает два варианта, которые может сделать пользователь). В первом тесте ( Тест выбора слайда A / B (рабочий) переход работает путем сдвига div слева направо. Два последующих слайда абсолютно позиционируются вправо: 100%, затем вправо: 0, используя: target

#target2:target {
        right: 0;
    }
    #target3:target {
        right: 0;
    }
    #target1, #target2, #target3 {
        transition: all 0.6s ease-out;
    }
    #target1 {
        z-index:1;
    }
    #target2 {
        z-index:2;
        right: 100%;
    }
    #target3 {
        z-index:3;
        right: 100%;
    }

Результат работает как надо - при нажатии на выбор 1A или 1B происходят переходы и отображаются правильные слайды.


Но во втором тесте , Тест выбора слайда A / B (не работает) , два последующих блока, слайд 2 и 3, абсолютно позиционируются слева: 100%, затем слева: 0, используя: target

#target2:target {
        left: 0;
    }
    #target3:target {
        left: 0;
    }
    #target1, #target2, #target3 {
        transition: all 0.6s ease-out;
    }
    #target1 {
        z-index:1;
    }
    #target2 {
        z-index:2;
        left: 100%;
    }
    #target3 {
        z-index:3;
        left: 100%;
    }

Происходит несколько вещей:

При нажатии на решение 1A:

  • Результат: Слайд 3 (# target3) перемещается в позицию без перехода.
  • Ожидается: Слайд 2 (# target2) появляется с правой стороны экрана.

Насколько я могу судить, нажатие на 1A активирует неправильная цель и / или Слайд 2 и 3 движутся влево (со Слайдом 2 b eing сдвинут за пределы экрана влево). Затем, если вы нажмете вариант 3A, переход работает правильно (скользит назад вправо, снова открывая слайд 1)

При нажатии на решение 1B:

  • Результат: Слайд 3 (# target3) внезапно появляется и перемещается за пределы экрана (влево) с переходом, показывая слайд 2 (# target2).
  • Ожидается: Slide 3 (# target3) слайды в правой части экрана.

Затем, если вы нажмете вариант 2B, переход работает правильно (sld ie возвращается вправо, снова открывая слайд 1)


Я пробовал этот переход с абсолютно позиционированием, используя top: 100% и top: 0, и bottom: 100% и bottom: 0

Возникает та же проблема: работает использование абсолютно позиционированных значений «top» , в то время как «нижние» значения создают нежелательное поведение.

Я хочу иметь возможность использовать переходы в любом направлении, конечной целью является то, что «направление» будет настраиваемым внутренним параметром в модуле Joomla. Модуль на самом деле написан, установлен и работает правильно, за исключением этой проблемы перехода.


Я не знаю, нарушает ли: target желаемое поведение, или я что-то делаю не так с абсолютное позиционирование CSS значений или и то, и другое. Или, если мое (ограниченное) понимание Flexbox все портит.

Я полностью открыт для использования другого метода получения желаемого поведения, показанного в рабочей версии (в идеале, используя только CSS), если это

Но до сих пор в моих rnet поисках я не нашел ни одного фрагмента кода или примеров одноэкранного интерфейса A / B, который я пытаюсь выполнить sh.

Я чрезвычайно благодарен за любую помощь!


РЕДАКТИРОВАТЬ: Я играл со значениями, чтобы увидеть, смогу ли я лучше понять, что происходит.

        #target2:target {
        left: 100%;
    }
    #target3:target {
        left: 100%;
    }
    #target1, #target2, #target3 {
        transition: all 0.6s ease-out;
    }
    #target1 {
        z-index:1;
    }
    #target2 {
        z-index:2;
        left: 100%;
    }
    #target3 {
        z-index:3;
        left: 100%;
    }

Теоретически (насколько я понимаю), с CSS выше не должно быть никаких изменений, поскольку остались оба значения: 100%

Но на практике нажатие на решение 1A или 1B вызывает # target2 и # target3 для перемещения по экрану (хотя и без перехода).

Затем я добавил несколько слайдов в относительно позиционированный оборачивающий div, и обнаружил, что все идентификаторы слайдов влияют на ed (# target2, # target3, # target4, # target5 et c.).

Я снова понимаю, что нажатие на href = "# target2" должно влиять только на # target2: target, но это влияет на все остальные идентификаторы слайдов, заставляя меня думать, что position: absolute и: target каким-то образом конфликтуют.

(бьет головой об стол)

Ответы [ 2 ]

1 голос
/ 27 мая 2020

Проблема, с которой вы столкнулись, действительно заключается в том, что position: absolute и таргетинг противоречат друг другу. Они конфликтуют из-за того, что браузер пытается прокрутить в нужное место, потому что вы используете теги привязки. Затем позиция начинает меняться, что приводит к исчезновению элемента, который вы хотите отобразить.

Итак, ваши два варианта заставить его действительно работать так, как вы хотите, - это предотвратить прокрутку браузера. например, откажитесь от тегов привязки, чтобы браузер не прокручивал вместо вас (может быть, добавление JS вместо этого?).

Или вы можете go целиком при прокрутке и не изменять местоположение из абсолютного позиционирования.


CSS единственное решение

Поскольку вы просили четные альтернативы (желательно без JS), здесь используется CSS привязка прокрутки ( CSS Уловки ) для выполнения тяжелых переходов. Вся ваша разметка одинакова.

Основные элементы этого решения, которые следует отметить:

элемент html - это тот, который имеет полосу прокрутки в этом случае, поэтому ему нужна прокрутка -snap-type и поведение

html {
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
}

Все цели должны быть точками привязки:

#target1,
#target2,
#target3 {
  scroll-snap-align: center;
}

Это были две основные вещи, чтобы заставить это работать на базовом уровне, но была пара других интересных дополнений, чтобы он выглядел немного лучше.

Нам нужно увеличить целевые значения до большего z-индекса, когда они нацелены, чтобы они всегда были на вершине.

#target2:target,
#target3:target {
  z-index: 5;
}

У цели 1 должно быть фиксированное положение, когда она не нацелена, поэтому похоже, что она остается в одном месте во время прокрутки (к сожалению, я не смог придумать хороший способ сделать обратное) .

#target1:not(:target) {
  position: fixed;
  left: 0;
}

В этом случае должен быть переход по z-индексу, чтобы target2 не сразу go под целевым 3, когда он покидает экран

 section:not(:target) {
  transition: z-index 2s ease-out;
}

body,
html {
  width: 100%;
  height: 100%;
  margin: 0;
  font-family: sans-serif;
}

html {
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  overflow: hidden;
}

.mainwrap {
  height: 100%;
  position: relative;
}

.flexwrap {
  position: relative;
  display: flex;
  height: 100%;
}

.contentwrap {
  display: flex;
  flex: 1;
}

figure {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 1;
  padding: 0;
  margin: 0;
}

.flexcolumn {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.leftbox,
.rightbox {
  padding: 5%;
}

.leftbox {
  color: #fff;
}

.rightbox {
  color: #574a46;
}

@media screen and (min-width: 993px) {
  .contentwrap {
    flex-direction: row;
  }
  figure {
    flex-direction: column;
  }
  .flexcolumn {
    justify-content: center;
  }
}

@media screen and (max-width: 992px) {
  .contentwrap {
    flex-direction: column;
  }
  figure {
    flex-direction: row;
  }
  .flexcolumn {
    justify-content: center;
  }
}

.drab {
  background-color: #676c27;
}

.orange {
  background-color: #ff9600;
}

.yellow {
  background-color: #ffcc00;
}

.burgundy {
  background-color: #83240f;
}

.lime {
  background-color: #cccc33;
}

.olive {
  background-color: #333300;
}

.navy {
  background-color: #000033;
}

a {
  color: #ffffff;
}

#target2:target,
#target3:target {
  z-index: 5;
}

#target1:not(:target) {
  position: fixed;
  left: 0;
}

 section:not(:target) {
  transition: z-index 2s ease-out;
}

#target1,
#target2,
#target3 {
  scroll-snap-align: center;
}

#target1 {
  z-index: 1;
}

#target2 {
  z-index: 2;
  left: 100%;
}

#target3 {
  z-index: 3;
  left: 100%;
}

.start {
  position: absolute;
  width: 100%;
  height: 100%;
}

.reset {
  position: absolute;
  height: 100%;
  width: 100%;
  overflow: hidden;
  /* left: 0%; */
  z-index: -1;
  /* transform: translateX(100%); */
}
<div id="decisionTree" class="mainwrap">
  <section class="start" id="target1">
    <div class="flexwrap">
      <div class="contentwrap">
        <figure id="tree1" class="fadebox leftbox navy">
          <div class="flexcolumn">
            <h3>I am Decision #1a</h3>
            <figcaption>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
            </figcaption>
          </div>
          <a href="#target2">CLICK</a>
        </figure>
        <figure id="tree2" class="fadebox rightbox yellow">
          <div class="flexcolumn">
            <h3>I am Decision #1b</h3>
            <figcaption>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
            </figcaption>
          </div>
          <a href="#target3">CLICK</a>
        </figure>
      </div>
    </div>
  </section>
  <section class="reset" id="target2">
    <div class="flexwrap">
      <div class="contentwrap">
        <figure id="tree1" class="fadebox leftbox olive">
          <div class="flexcolumn">
            <h3>I am Decision #2a</h3>
            <figcaption>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
            </figcaption>
          </div>
          <a href="#target1">CLICK</a>
        </figure>
        <figure id="tree2" class="fadebox rightbox orange">
          <div class="flexcolumn">
            <h3>I am Decision #2b</h3>
            <figcaption>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
            </figcaption>
          </div>
          <a href="#target1">CLICK</a>
        </figure>
      </div>
    </div>
  </section>
  <section class="reset" id="target3">
    <div class="flexwrap">
      <div class="contentwrap">
        <figure id="tree1" class="fadebox leftbox burgundy">
          <div class="flexcolumn">
            <h3>I am Decision #3a</h3>
            <figcaption>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
            </figcaption>
          </div>
          <a href="#target1">CLICK</a>
        </figure>
        <figure id="tree2" class="fadebox rightbox lime">
          <div class="flexcolumn">
            <h3>I am Decision #3b</h3>
            <figcaption>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
            </figcaption>
          </div>
          <a href="#target1">CLICK</a>
        </figure>
      </div>
    </div>
  </section>
</div>

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


JavaScript решение

Как уже упоминалось, решение JS подходит, если оно объяснено ну / достаточно просто:

В этом случае JS выглядит следующим образом. Фактические фрагменты снабжены комментариями, чтобы было легче следить за ними. В общем, вместо использования :target это решение работает путем переключения класса .selected в элементах. Основное преимущество этого заключается в том, чтобы избавиться от событий прокрутки браузера, которые предоставляют теги привязки.

function clickHandler(target){
  // Get the element that should be selected
  const elem = document.querySelector(target);
  // There were no elements to be selected
  if(!elem) return;
  // Get the old selected element (if any)
  const prevElem = document.querySelector('.selected');
  if(prevElem){
    // If there was a previously selected element, it isn't anymore
     prevElem.classList.remove('selected'); 
  }
  // Make the new element selected
  elem.classList.add('selected');
}

Изменения CSS также незначительны:

вместо использования :target, мы используем .selected

#target2.selected,
#target3.selected {
  left: 0;
}

Внесенные мной изменения html меняли теги a на кнопки (чтобы быть более семантически правильными) и давали им обработчик события onClick:

<button onClick="clickHandler('#target3')">CLICK</button>

Для отображения при переполнении стека из-за того, что он по умолчанию обеспечивает такое короткое и приземистое окно, я установил min-height равным 390 пикселей (так что есть базовый размер, чтобы избежать странностей, связанных с тем, что все основано на%, когда они не подходят)

html {
  min-height: 390px;
  overflow-x: hidden;
  overflow-y: auto;
}

function clickHandler(target) {
  // Get the element that should be selected
  const elem = document.querySelector(target);
  // There were no elements to be selected
  if (!elem) return;
  // Get the old selected element (if any)
  const prevElem = document.querySelector('.selected');
  if (prevElem) {
    // If there was a previously selected element, it isn't anymore
    prevElem.classList.remove('selected');
  }
  // Make the new element selected
  elem.classList.add('selected');
}
html {
  min-height: 390px;
  overflow-x: hidden;
  overflow-y: auto;
}

body,
html {
  width: 100%;
  height: 100%;
  margin: 0;
  font-family: sans-serif;
}

.mainwrap {
  height: 100%;
  position: relative;
}

.flexwrap {
  position: relative;
  display: flex;
  height: 100%;
}

.contentwrap {
  display: flex;
  flex: 1;
}

figure {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 1;
  padding: 0;
  margin: 0;
}

.flexcolumn {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.leftbox,
.rightbox {
  padding: 5%;
}

.leftbox {
  color: #fff;
}

.rightbox {
  color: #574a46;
}

@media screen and (min-width: 993px) {
  .contentwrap {
    flex-direction: row;
  }
  figure {
    flex-direction: column;
  }
  .flexcolumn {
    justify-content: center;
  }
}

@media screen and (max-width: 992px) {
  .contentwrap {
    flex-direction: column;
  }
  figure {
    flex-direction: row;
  }
  .flexcolumn {
    justify-content: center;
  }
}

.drab {
  background-color: #676c27;
}

.orange {
  background-color: #ff9600;
}

.yellow {
  background-color: #ffcc00;
}

.burgundy {
  background-color: #83240f;
}

.lime {
  background-color: #cccc33;
}

.olive {
  background-color: #333300;
}

.navy {
  background-color: #000033;
}

a {
  color: #ffffff;
}

#target2.selected,
#target3.selected {
  left: 0;
}

#target1,
#target2,
#target3 {
  transition: all 0.6s ease-out;
}

#target1 {
  z-index: 1;
}

#target2 {
  z-index: 2;
  left: 100%;
}

#target3 {
  z-index: 3;
  left: 100%;
}

.start {
  position: absolute;
  width: 100%;
  height: 100%;
}

.reset {
  position: absolute;
  height: 100%;
  width: 100%;
  overflow: hidden;
}
<div id="decisionTree" class="mainwrap">
  <section class="start" id="target1">
    <div class="flexwrap">
      <div class="contentwrap">
        <figure id="tree1" class="fadebox leftbox navy">
          <div class="flexcolumn">
            <h3>I am Decision #1a</h3>
            <figcaption>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</figcaption>
          </div>
          <button onClick="clickHandler('#target2')">CLICK</button>
        </figure>
        <figure id="tree2" class="fadebox rightbox yellow">
          <div class="flexcolumn">
            <h3>I am Decision #1b</h3>
            <figcaption>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</figcaption>
          </div>
          <button onClick="clickHandler('#target3')">CLICK</button>
        </figure>
      </div>
    </div>
  </section>
  <section class="reset" id="target2">
    <div class="flexwrap">
      <div class="contentwrap">
        <figure id="tree1" class="fadebox leftbox olive">
          <div class="flexcolumn">
            <h3>I am Decision #2a</h3>
            <figcaption>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</figcaption>
          </div>
          <button onClick="clickHandler('#target1')">CLICK</button>
        </figure>
        <figure id="tree2" class="fadebox rightbox orange">
          <div class="flexcolumn">
            <h3>I am Decision #2b</h3>
            <figcaption>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</figcaption>
          </div>
          <button onClick="clickHandler('#target1')">CLICK</button>
        </figure>
      </div>
    </div>
  </section>
  <section class="reset" id="target3">
    <div class="flexwrap">
      <div class="contentwrap">
        <figure id="tree1" class="fadebox leftbox burgundy">
          <div class="flexcolumn">
            <h3>I am Decision #3a</h3>
            <figcaption>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</figcaption>
          </div>
          <button onClick="clickHandler('#target1')">CLICK</button>
        </figure>
        <figure id="tree2" class="fadebox rightbox lime">
          <div class="flexcolumn">
            <h3>I am Decision #3b</h3>
            <figcaption>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</figcaption>
          </div>
          <button onClick="clickHandler('#target1')">CLICK</button>
        </figure>
      </div>
    </div>
  </section>
</div>
0 голосов
/ 27 мая 2020

Эй, чувак, будет намного проще, если ты сделаешь кодовый код или jsfiddle. Это довольно длинное объяснение, и его довольно сложно довести до конца. извините, у меня нет решения, но если вы сделаете jsfiddle, я помогу вам чем могу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...