Без полной HTML
трудно помочь столько, сколько я хотел бы.Основная идея состоит в том, чтобы использовать CSS-переменные и обновить переменную от наших JavaScript
слушателей.
Вот пример, который обновляет ширину элемента .typ-wrap
до половины размера области просмотра.
// Check on load
checkWindowWidth();
// Check on resize
$(window).on('resize', handleResize);
function handleResize() {
checkWindowWidth();
}
function checkWindowWidth() {
$(":root")[0].style.setProperty('--window-width', $(window).width());
$('.typ-wrap').attr('data-window-width', $(window).width());
}
html,
body {
margin: 0;
}
:root {
--window-width: 0;
}
.typ-wrap {
display: inline-block;
width: calc(var(--window-width) / 2 * 1px);
height: 50px;
background: green;
position: relative;
}
.typ-wrap::after {
content: attr(data-window-width) 'px';
position: absolute;
bottom: -1.5em;
left: 50%;
transform: translateX(-50%);
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="typ-wrap" data-window-width=""></div>
Обновление (решение!)
Глядя на страницу MDN для пользовательской полосы прокрутки, яне видел упоминаний о :end
и :start
в качестве суффикса к ::-webkit-scrollbar-track-piece
, что заставило меня задуматься: почему бы не установить вместо этого оба поля? Так вот, что я и сделал.
CSS
Я добавил:
.typ-wrap::-webkit-scrollbar-track-piece {
margin-left: calc(((var(--window-width) * 1px) - 302px) / 2);
margin-right: calc(((var(--window-width) * 1px) - 302px) / 2);
…
}
В нашем JavaScript
мы устанавливаем ширину окна как для загрузки страницы, так и для события изменения размера.
$(":root")[0].style.setProperty('--window-width', $(window).innerWidth());
Демо (только Chrome):
// Check on load
checkWindowWidth();
// Check on resize
$(window).on('resize', handleResize);
function handleResize() {
checkWindowWidth();
}
function checkWindowWidth() {
$(":root")[0].style.setProperty('--window-width', $(window).innerWidth());
}
:root {
--window-width: 0;
}
html {
font-size: 62.5%;
}
body {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-size: 100%;
vertical-align: baseline;
background: transparent;
box-sizing: border-box;
list-style-type: none;
}
/* reset */
.typ {
position: relative;
width: 100%;
}
.typ::after {
content: '';
position: absolute;
z-index: -1;
width: 30.2rem;
height: 1.6rem;
bottom: 0;
left: 0;
right: 0;
margin: auto;
background: url("https://cdn-ak.f.st-hatena.com/images/fotolife/O/O2_milk/20190228/20190228080150.png");
}
.typ-wrap {
position: relative;
box-sizing: border-box;
width: 100%;
margin-bottom: 8.3rem;
overflow-x: scroll;
overflow-y: hidden;
writing-mode: bt-lr;
-webkit-appearance: none;
}
.typ-wrap::-webkit-scrollbar {
display: block;
width: 33.2rem;
}
.typ-wrap::-webkit-scrollbar-track {
-webkit-appearance: none;
background: transparent;
}
.typ-wrap::-webkit-scrollbar-track-piece {
margin-left: calc(((var(--window-width) * 1px) - 302px) / 2);
margin-right: calc(((var(--window-width) * 1px) - 302px) / 2);
background: transparent;
}
.typ-wrap::-webkit-scrollbar-thumb {
width: 1.5rem;
height: 1.3rem;
background: #fff;
border: 1px solid #000;
}
.typ-wrap ul {
width: 100%;
height: 31.9rem;
white-space: nowrap;
}
.typ-wrap li {
display: inline-block;
}
.typ-wrap li:first-child {
margin-left: 3rem;
}
.typ-wrap li:last-child {
margin-right: 3rem;
}
.typ-wrap li+li {
margin-left: 3rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="typ">
<div class="typ-wrap">
<ul>
<li>
<a href=""><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/O/O2_milk/20190228/20190228075715.png"
alt="あ=a" /></a>
</li>
<li>
<a href=""><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/O/O2_milk/20190228/20190228075712.png"
alt="い=b" /></a>
</li>
<li>
<a href=""><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/O/O2_milk/20190228/20190228075710.png"
alt="う=c" /></a>
</li>
<li>
<a href=""><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/O/O2_milk/20190228/20190228075706.png"
alt="え=d" /></a>
</li>
<li>
<a href=""><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/O/O2_milk/20190228/20190228075704.png"
alt="お=e" /></a>
</li>
<li>
<a href=""><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/O/O2_milk/20190228/20190228075810.png"
alt="か=f" /></a>
</li>
<li>
<a href=""><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/O/O2_milk/20190228/20190228075807.png"
alt="き=g" /></a>
</li>
<li>
<a href=""><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/O/O2_milk/20190228/20190228075805.png"
alt="く=h" /></a>
</li>
<li>
<a href=""><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/O/O2_milk/20190228/20190228075802.png"
alt="け=i" /></a>
</li>
<li>
<a href=""><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/O/O2_milk/20190228/20190228075759.png"
alt="こ=j" /></a>
</li>
</ul>
</div>
Обновление II (Некоторое объяснение)
Итак, какого черта эта строка в любом случае?
margin-left: calc(((var(--window-width) * 1px) - 302px) / 2);
Это CSS
, но довольно вложенный и сложный вид.Это не так уж плохо.Давайте разберемся с этим.
calc()
Думайте об этом как об умном калькуляторе для Интернета.Он встроен в CSS
и может сделать для нас несколько хитрых вещей, таких как add 41em + 50px
.Большинство людей не могут вычислить это вне своей головы, но это не проблема для calc()
.Так же, как настоящий калькулятор, вы можете выполнять несколько операций одновременно.
Единственное предостережение в том, что по обе стороны от ваших операторов должен существовать пробел (+, -, *, /).
Хорошо
calc(40% + 5px);
Плохо
calc(40%+5px);
Теперь у нас есть эта часть выражения:
((var(--window-width) * 1px)
Давайте пойдем наизнанку.Ниже приводится число, которое мы генерируем с помощью JavaScript
, как при первой загрузке, так и после изменения размера.
var(--window-width)
Дело в том, что число не имеет единиц измерения в конце.Это может быть 511
, но не 511px
.Это приводит нас к следующей части этого длинного уравнения, где мы умножаем ширину без единиц измерения * 1px
.Помните, когда я говорил, что calc()
может принимать совершенно разные единицы и объединять их в одно значение?Ну, умножив на 1px
, я заставляю эту ширину равняться px
width.
Теперь, когда у нас есть ширина окна в формате px
, мы вычитаем 302px
изэто, константа из вашего уравнения.Наконец, мы берем результат из всего этого и делим его на 2, учитывая половину ширины самой полосы прокрутки.Теперь у нас есть динамически центрированная полоса прокрутки, готовая к действию.
Хорошо, переведите дыхание.Чтобы ответить на ваш последний вопрос, я считаю, что небольшой сдвиг, который вы иногда видите, сводится к аномалиям субпиксельного рендеринга, которые могут возникать в браузере при заданной ширине экрана.Иногда я вижу сдвиг, но не всегда.Вероятно, это зависит от того, когда произошло событие изменения размера и насколько точны эти окончательные расчеты.Я бы связал это с трудностью решения проблем, возникающих при таком динамическом позиционировании элементов, которое иногда перезапускается каждую секунду.Я не уверен, что смогу решить эту последнюю часть без гораздо большего расследования и работы.
Я надеюсь, что через весь этот вопрос вы узнали несколько вещей.Может быть, вы можете помочь кому-нибудь в будущем.Подобные вопросы делают участие в этом сайте увлекательным.Приятно познакомиться, POP!
jsFiddle