Создание бесшовного вложенного прокрутки прокрутки

Я пытаюсь создать серию оконных размерных div с внутренними divs размеров переменных > размер окна. Уловку нужно прокручивать, как если бы divs не были вложены.

Короче говоря, я хочу ЭТО:

css{
     block{ height:100wh; }
     innerBlockSmall{ height:100wh; }
     innerBlockLarge{ height:200wh; }
}


<div class="block">
    <div class="innerBlockLarge"></div>
</div>
<div class="block">
    <div class="innerBlockSmall"></div>
</div>

https://jsfiddle.net/cbuh8psd/

действовать так же, как ЭТО

css{
     innerBlockSmall{ height:100wh; }
     innerBlockLarge{ height:200wh; }
}

    <div class="innerBlockLarge"></div>
    <div class="innerBlockSmall"></div>

https://jsfiddle.net/t6zrvo7u/1/

К сожалению, прокрутка "Фокус" срабатывает hover по прокручиваемому элементу. В этом случае это нежелательное поведение.

Есть два возможных решения, о которых я сейчас знаю.

  • Вручную назначает прокрутку "Фокус" через javascript. (Оптимальное)

  • Полностью переписывает javascript по умолчанию для прокрутки по умолчанию, для пример библиотеки ISCROLL5.
    (хорошо, если удар производительности мал)

К сожалению, просмотрев документацию developer.mozilla HTML5, я не перешел ни в какую сторону, чтобы прокрутить "Фокус" к элементу через javascript.

Что касается варианта 2: у ISCROLL5 было нежелательное поражение производительности с более чем 15-20 прокручивающимися div.

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

Ответ 1

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

К сожалению, я не могу вспомнить проект, который я написал для этого кода, хотя один из способов добиться этого - сделать себя компонентом прокрутки. Этот компонент полосы прокрутки действительно обеспечил бы поддельную полосу прокрутки, но обеспечивал бы родной интерфейс. Итак, как вы это делаете?

  • Вы определяете ширину полосы прокрутки, принимая разницу между элементом с и без overflow: scroll. Пусть это будет scrollWidth
  • Вы создаете <div> с overflow: auto шириной scrollWidth и position: fixed на месте с правой стороны тела. Пусть свойство scrollTop будет scrollPosition.
  • Внутри элемента вы добавляете еще один <div> с шириной 0 (это, по крайней мере, работает в Chrome, проверьте, относятся ли другие браузеры по-другому) и пусть высота будет documentLength.
  • Теперь вы можете полностью управлять полосой прокрутки, установив documentLength и scrollPosition любым способом. В вашем случае вы установите documentLength как объединенные значения прокруткиHeight каждого элемента и scrollPosition на основе относительного scrollTop в этих узлах.

В этом jsfiddle можно найти очень базовую демонстрацию концепции (а не реализации) (обратите внимание на width полоса прокрутки привязана к 20px в этом случае и динамический код вообще отсутствует).

Ответ 2

Это решение позволяет прокручивать весь документ, сохраняя возможность прокрутки каждого вложенного div мышью. Надеюсь, я правильно тебя понял.

Это просто концепция, она не предотвращает прокрутку вложенных элементов вместе с окном. Но его можно улучшить.

Array.prototype.slice.call( document.getElementsByClassName('sbRemover') )
.forEach(function (div) {
    var scroll = 0,
        mousedown = false,
        mouseBtnHandler = function (e) {
            mousedown = e.type == 'mousedown';
        }
    
    div.addEventListener('scroll', function (e) {
        // Change of div scrollTop. Negative when scrolling down
        var diff = scroll - e.target.scrollTop;
        // Save new scroll value to be able to compare with it later
        scroll = e.target.scrollTop;
        // Do nothing when div is scrolled by dragging the scrollbar
        if (!mousedown) {
            // Scroll the window to the same amount of pixels the div was scrolled
            window.scrollTo(window.pageXOffset, window.pageYOffset - diff);
        }
    });
    div.addEventListener('mouseup', mouseBtnHandler);
    div.addEventListener('mousedown', mouseBtnHandler);
});
body, div {
    margin: 0;
    padding: 0;
}
.block{
    position: relative;
    width:100vw;
    height:100vh;
    overflow: hidden;
    z-index: 1;
    opacity: 100;
}
.sbRemover{
    width:100%;
    height:100%;
    padding-right:15px;
    overflow: auto;
}
.largeContent{
    height:225vh;
}
.smallContent{
    height:100vh;
}
<div id="simpleCanvas">
  <div class="block" style="background-color: blue">
    <div class="sbRemover">
      <div id="ok" class="largeContent" style="background-image: url('http://silviahartmann.com/background-tile-art/images/grey-repeating-background-8.jpg');"></div>
    </div>
  </div>
  <div class="block" style="background-color: red;">
    <div class="sbRemover">
      <div class="largeContent" style="background-image: url('http://a1star.com/images/star--background-seamless-repeating9.jpg');"></div>
    </div>
  </div>
  <div class="block" style="background-color: green">
    <div class="sbRemover">
      <div class="smallContent"></div>
    </div>
  </div>
  <div class="block" style="background-color: blue">
    <div class="sbRemover">
      <div class="smallContent"></div>
    </div>
  </div>
  <div class="block" style="background-color: red;">
    <div class="sbRemover">
      <div class="largeContent" style="background-image: url('http://people.stfx.ca/x2011/x2011ane/info102/assignment1/11500341-abstract-colorful-repeating-background.jpg');"></div>
    </div>
  </div>
  <div class="block" style="background-color: green">
    <div class="sbRemover">
      <div class="smallContent"></div>
    </div>
  </div>
</div>