Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Как с помощью скрипта высчитать ширину полосы прокрутки? (https://javascript.ru/forum/dom-window/71320-kak-s-pomoshhyu-skripta-vyschitat-shirinu-polosy-prokrutki.html)

LADYX 10.11.2017 10:33

Как с помощью скрипта высчитать ширину полосы прокрутки?
 
Добрый день!
У меня есть вот такая разметка. С помощью стиля высчитывается ширина полосы прокрутки (за основу берется 16px как у большинства браузерах). Но как мы знаем, в редких и мобильных браузерах ширина полосы прокрутки может колебаться от 14px до 18px, а кое-где быть даже равна нулю.
Скажите, пожалуйста, а как можно с помощью скрипта высчитывать полосу прокрутки и этим же скриптом уже корректировать стиль (margin и width) для блока .wrp?
Спасибо!
<style>
* {
  box-sizing: border-box;
}
body {
  margin: 0;
  padding: 0;
}
.wrapper {
  background-color: burlywood;
  text-align: justify;
  margin: 0 auto;
  width: 200px;
  padding: 0 100px 0 0;
}
.wrp {
  background-color: chocolate;
  height: 100%;
  min-height: 100vh;
  padding: 0;
  margin: 0 calc(8px - 50vw) 0 calc(108px - 50vw);
  width: calc(100vw - 16px);
}
</style>
<div class="wrapper">
много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста
<div class="wrp">Этот блок нужно растянуть по ширине экрана, за пределы его родителя</div>
много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста
</div>

Nexus 10.11.2017 11:09

Win 7, Chrome lts:
var scroll_bar_width=$('body').css('overflow','hidden').width()-$('body').css('overflow','auto').width();
alert(scroll_bar_width);//17


Ps. Почему не разместить .wrp вне .wrapper?

рони 10.11.2017 11:18

LADYX,
Найти эту ширину можно вот так

LADYX 10.11.2017 11:37

Цитата:

Сообщение от Nexus
Ps. Почему не разместить .wrp вне .wrapper?

Nexus,
это уже готовая разметка, я не могу ее трогать.

рони,
да, я видел уже это решение. Но, как я понимаю, это не совсем то, что нужно. Как же мне им вывести margin и width для блока .wrp?

Nexus 10.11.2017 11:47

Может так?
https://jsfiddle.net/3m91ubrg/

рони 10.11.2017 11:59

LADYX,
<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style>
* {
  box-sizing: border-box;
}
body {
  margin: 0;
  padding: 0;
}
.wrapper {
  background-color: burlywood;
  text-align: justify;
  margin: 0 auto;
  width: 200px;
  padding: 0 100px 0 0;
}
.wrp {
  background-color: chocolate;
  height: 100%;
  min-height: 100vh;
  padding: 0;
  margin: 0 calc(8px - 50vw) 0 calc(108px - 50vw);
  width: calc(100vw - 16px);
}
</style>
</head>

<body>

<div class="wrapper">
много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста
<div class="wrp">Этот блок нужно растянуть по ширине экрана, за пределы его родителя</div>
много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста
</div>
<script>
  // создадим элемент с прокруткой
var div = document.createElement('div');

div.style.overflowY = 'scroll';
div.style.width =  '50px';
div.style.height = '50px';

// при display:none размеры нельзя узнать
// нужно, чтобы элемент был видим,
// visibility:hidden - можно, т.к. сохраняет геометрию
div.style.visibility = 'hidden';

document.body.appendChild(div);
var scrollWidth = div.offsetWidth - div.clientWidth;
document.body.removeChild(div);
var x = ".wrp{ width: calc(100vw - "+scrollWidth+"px); margin: 0 calc("+(scrollWidth/2)+"px - 50vw) 0 calc(108px - 50vw);}";
var style = document.createElement('style');
style.textContent = x;
document.head.appendChild(style);
</script>
</body>
</html>

LADYX 10.11.2017 12:53

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

Цитата:

Сообщение от Nexus

Nexus,
да, это вариант работает.

Странно, скажите, пожалуйста, а зачем тогда использовать такой объемный вариант, как этот
Цитата:

Сообщение от рони
Найти эту ширину можно вот так

если можно обойтись таким простым вариантом, как этот?
Цитата:

Сообщение от Nexus

Прошу меня простить за глупые вопросы, но все же.

Nexus 10.11.2017 12:59

LADYX, мой вариант годится, если соблюдены определенные условия:
1. JQ подключена;
2. .wrp является потомком .wrapper.

Вариант рони не имеет таких зависимостей.

рони 10.11.2017 13:03

Цитата:

Сообщение от LADYX
в скрипте 50px - не могу понять, это что за число, откуда оно берется?

от фонаря -- размер любой, нам нужно только стороны прокрутки на чём-то создать.(div.style.overflowY = 'scroll';)

рони 10.11.2017 13:03

Цитата:

Сообщение от LADYX
мы ведь снова в скрипте берем за основу ширину полосы в 16px

где???

LADYX 10.11.2017 13:18

Nexus,
Цитата:

Сообщение от Nexus
2. .wrp является потомком .wrapper.

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

Сообщение от рони
где???

так вот же мы в скрипте и указываем
calc(108px - 50vw);}

Так а почему же появляется нижняя полоса прокрутки? Обратите внимание, слева небольшое расстояние, так понимаю, из-за него же она и появляется. Откуда она берется?

рони 10.11.2017 13:26

Цитата:

Сообщение от LADYX
так вот же мы в скрипте и указываем
calc(108px - 50vw);}

не могли бы вы пояснить что здесь указано?

Nexus 10.11.2017 13:26

LADYX,
Тут нет зависимости от родителей:
https://jsfiddle.net/3m91ubrg/1/

Nexus 10.11.2017 13:28

Цитата:

Сообщение от рони
не могли бы вы пояснить что здесь указано?

Какие-то 108px минус 50% ширины viewport'а.

Что такое "108px" тоже интересно.

Ps. 108px - это .wrp width (100px) + scrollbar width (16px) *.5

рони 10.11.2017 13:42

:write:
<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style>
* {
    box-sizing:  border-box;
}
body {
  margin: 0;
  padding: 0;
}
.wrapper {
  background-color: burlywood;
  text-align: justify;
  margin: 0 auto;
  width: 200px;
  padding: 0 100px 0 0;
}
.wrp {
  background-color: chocolate;
  height: 100%;
  min-height: 100vh;
  padding: 0;

}
</style>
</head>

<body>

<div class="wrapper">
много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста
<div class="wrp">Этот блок нужно растянуть по ширине экрана, за пределы его родителя</div>
много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста
</div>
<script>
window.addEventListener('DOMContentLoaded', function() {
var scrollWidth = window.innerWidth  - document.documentElement.clientWidth ;
var x = ".wrp{ width: calc(100vw - "+scrollWidth+"px); margin: 0 calc("+(scrollWidth/2)+"px - 50vw) 0 calc(100% + "+(scrollWidth/2)+"px - 50vw);}";
var style = document.createElement('style');
style.textContent = x;
document.querySelector("head").appendChild(style);
    });

</script>
</body>
</html>

LADYX 10.11.2017 13:45

Цитата:

Сообщение от LADYX
108px

ну да, я так понимаю, 8 - это половина ширины полосы прокрутки, ну так же?
Цитата:

Сообщение от LADYX
из-за этого может быть и не работает

Прошу меня простить. И этот вариант работает. Это моя ошибка. Просто у меня блок .wrp идет не класс, а ид. И мне нужна было в скрипте указать не
$('.wrp')

а
$('#wrp')

Это моя невнимательность, простите. Всё работает, как нужно.
Nexus,
рони,
Огромное спасибо!

Nexus 10.11.2017 13:46

рони,
Цитата:

Сообщение от рони
calc("+(100+scrollWidth/2)+"px - 50vw);

Лучше так:
calc(100% + "+(scrollWidth/2)+"px - 50vw);

LADYX 10.11.2017 13:48

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

рони,
Nexus,
ОГРОМНЕЙШЕЕ ВАМ СПАСИБО!!!

рони 10.11.2017 13:48

Nexus,
заменил

Nexus 10.11.2017 14:06

Немного изменил генерируемый css.
<!DOCTYPE html>
<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style>
* {
    box-sizing:  border-box;
}
body {
  margin: 0;
  padding: 0;
}
.wrapper {
  background-color: burlywood;
  text-align: justify;
  margin: 0 auto;
  width: 200px;
  padding: 0 100px 0 0;
}
.wrp {
  background-color: chocolate;
  height: 100%;
  min-height: 100vh;
  padding: 0;

}
</style>
</head>

<body>

<div class="wrapper">
много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста
<div class="wrp">Этот блок нужно растянуть по ширине экрана, за пределы его родителя</div>
много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста много текста
</div>
<script>
	window.addEventListener('DOMContentLoaded', function() {
		var scrollWidth = window.innerWidth  - document.documentElement.clientWidth ;
		var x = '.wrp{'
			+'width: calc(100vw - '+scrollWidth+'px);'
			+'margin-left:calc(-.5 * (100vw - '+scrollWidth+'px) + 100%);'
		+'}';
		var style = document.createElement('style');
		style.textContent = x;
		document.querySelector("head").appendChild(style);
	});
</script>
</body>
</html>
Тут можно ширину окна изменить рил тайм:
https://jsfiddle.net/j2e6pL1t/
PS. Если изменить ширину .wrapper, то работает неправильно.

LADYX 11.11.2017 22:00

Nexus,
прошу меня простить за вновь поднятую тему. При добавлении этого скрипта
var body_width=$('body').width(),
		$wrp=$('.wrp');
    
$wrp.css({
    width:body_width,
    'margin-left':-$wrp.offset().left
});

происходит конфликт скриптов. А именно все скрипты, которые находятся ниже его, перестают работать. Если я этот скрипт располагаю самым последним, то тогда все скрипты работают корректно. Если я заключаю его в
~function () {
}();

то это не помогает избежать конфликта.
Скажите, пожалуйста, что можно сделать?

рони 11.11.2017 22:08

LADYX,
консоль что пишет?

LADYX 11.11.2017 22:14

Цитата:

Сообщение от рони
консоль что пишет?

рони,
показывает на ошибку в строке номер такой-то, на этой строке выходит:
'margin-left':-$wrp.offset().left

да, и подчеркивает в этой строке волной
).left

рони 11.11.2017 22:19

LADYX,
скорее всего элемента $('.wrp'); ещё нет
сделайте так
$(function() {
var body_width=$('body').width(),
    $wrp=$('.wrp');

$wrp.css({
    width:body_width,
    'margin-left':-$wrp.offset().left
});

});

LADYX 11.11.2017 22:22

рони,
я уже так тоже пробовал, не помогает

рони 11.11.2017 22:32

LADYX,
делайте макет с проблемой или ждите телепата.
что будет в консоли, код ниже
$(function() {
var body_width=$('body').width(),
    $wrp=$('.wrp');
         console.log($wrp.length)
$wrp.css({
    width:body_width,
    'margin-left':-$wrp.offset().left
});

});

Nexus 11.11.2017 23:43

LADYX,
Цитата:

Сообщение от LADYX
Прошу меня простить. И этот вариант работает. Это моя ошибка. Просто у меня блок .wrp идет не класс, а ид.


LADYX 12.11.2017 12:53

Nexus,
нет, не в этом дело. Сейчас скрипт у меня вот такой:
$(function() {
  function update() {
    var body_width=$('body').width(), $uf=$('#pp-uf_range');

    $uf.css({
      width:body_width,
      'margin-left':-$uf.offset().left
    });
	console.log($uf.length)
  }

  $(window).resize(update);
  update();
});

рони,
в консоли вот что:
Uncaught TypeError: Cannot read property 'left' of undefined
    at update (scripts.js:113)
    at HTMLDocument.<anonymous> (scripts.js:119)
    at i (jquery.js?v=22:2)
    at Object.fireWith [as resolveWith] (jquery.js?v=22:2)
    at Function.ready (jquery.js?v=22:2)
    at HTMLDocument.J (jquery.js?v=22:2)

scripts.js:113 это:
'margin-left':-$uf.offset().left

подчеркивает
).left

scripts.js:119 это:
update();

Цитата:

Сообщение от рони
делайте макет с проблемой

рони,
я правильно дал информацию? Или не то что нужно? Тогда ткните меня, пожалуйста, носом)

Nexus 12.11.2017 13:01

LADYX, попробуйте так и смотрите консоль:
$(function(){
  $(window).resize(function(){
    var body_width=$('body').width(), 
	$uf=$('#pp-uf_range');
	
	if(!$uf.length)
		throw new Error('Element «#pp-uf_range» not found');

    $uf.css({
      width:body_width,
      'margin-left':-$uf.offset().left
    });
  }).resize();
});

У вас элемента нет на странице.

LADYX 12.11.2017 13:22

Nexus,
конфликт решается заменой строки
$uf.css({

на
$uf.length && $uf.css({

но тогда появляется другая проблема. Есть у меня другой скрипт
$(function() {
  $(window).scroll(function() {
    var windowScroll = $(window).scrollTop();
    var element = $('.pp-sections');
    var distanceTop = element.offset().top - ($(window).height() / 2);
    var distanceHeight = element.offset().top - ($(window).height() / 2 - element.height());
    if (windowScroll > distanceTop && windowScroll < distanceHeight)
      $('#panel-pp').animate({ 'left': '0px' }, 500);
    else
      $('#panel-pp').stop(true).animate({ 'left': '-146px' }, 200);
  });
});

И на страницах, где нет блока .pp-sections, в консоли появляется ошибка в строке
var distanceTop = element.offset().top - ($(window).height() / 2);

Если обернуть этот скрипт в
~function () {
}();

то это не помогает. Что можно сделать?
Простите меня за миллион вопросов, я сам уже запарился, ни одно, так другое :(

Nexus 12.11.2017 16:34

Цитата:

Сообщение от LADYX
конфликт решается заменой строки

никакого конфликта нет, есть банальное отсутствие элемента на странице.
Цитата:

Сообщение от LADYX
на страницах, где нет блока .pp-sections, в консоли появляется ошибка

Ну а как она не появится, если вы зная, что такого элемента на странице нет, все равно пытаетесь с ним взаимодействовать?
Проверить есть элемент на странице или нет можно так:
var element = $('.pp-sections');
if(element.length)
    alert('Элемент есть');
else
    alert('Элемента нет');

LADYX 12.11.2017 20:48

Цитата:

Сообщение от Nexus
никакого конфликта нет, есть банальное отсутствие элемента на странице.

да, вы конечно правы, так и есть до меня доперло, как до жирафа на седьмые сутки.
Nexus,
видите, что получается, есть у меня одна категория, в которой ряд страниц. И на одной из них есть блок div .pp-sections. Так вот на этой странице естественно никаких ошибок не возникает. А на всех остальных страницах появляется ошибка, в связи с чем и не работают все остальные скрипты, которые расположены ниже этого скрипта. Но я не имею такой возможности отдельно именно для этой страницы подключать отдельный файл с этим скриптом, поэтому этот скрипт находится в общем файле со всеми скриптами. Так вот скажите, пожалуйста, возможно ли что-то сделать с этим скриптом, чтобы он срабатывал только тогда, когда на странице есть такой блок, а если на странице такого блока нет, то чтобы этот скрипт полностью игнорировался? Реально ли такое сделать?

рони 12.11.2017 21:38

Цитата:

Сообщение от LADYX
Реально ли такое сделать?

:blink:
Цитата:

Сообщение от Nexus
Проверить есть элемент на странице или нет можно так:

:-?

LADYX 13.11.2017 12:16

рони,
делаю так
$(function() {
  $(window).scroll(function() {
    var windowScroll = $(window).scrollTop();
    var element = $('.pp-sections');
if(element.length) {
    var distanceTop = element.offset().top - ($(window).height() / 2);
    var distanceHeight = element.offset().top - ($(window).height() / 2 - element.height());
    if (windowScroll > distanceTop && windowScroll < distanceHeight)
      $('#panel-pp').animate({ 'left': '0px' }, 500);
    else
      $('#panel-pp').stop(true).animate({ 'left': '-146px' }, 200);
}
  });
});

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

Nexus 13.11.2017 12:32

LADYX, в этом участке кода синтаксических ошибок нет.

LADYX 13.11.2017 12:50

Nexus,
Цитата:

Сообщение от Nexus
LADYX, в этом участке кода синтаксических ошибок нет.

Да, вы правы. Увидел свою ошибку. Теперь всё работает как нужно.

Nexus,
рони,
огромнейшее вам спасибо за помощь и терпение! Удачи!


Часовой пояс GMT +3, время: 10:51.