Подтвердить что ты не робот

Учет ширины полосы прокрутки при позиционирующем элементе

У меня есть макет, который имеет максимальную ширину и который центрируется по горизонтали, когда ширина экрана больше этого максимума. Макет включает фиксированный заголовок и меню; когда ширина экрана меньше макс, позиция меню left 0, и, когда ширина экрана превышает максимальную, позиция меню left должна быть заподлицо с левым краем остальной части макета.

Вот как это должно выглядеть:

*{box-sizing:border-box;margin:0;padding:0;}
header{
    align-items:center;
    background:#eee;
    border-bottom:1px solid #999;
    display:flex;
    height:100px;
    left:0;
    justify-content:center;
    padding:0 10px;
    position:fixed;
    right:0;
    top:0;
}
h1{
    height:60px;
    position:relative;
    width:calc(100% - 40px);
    max-width:740px;
    z-index:2;
}
img{
    height:100%;
    width:auto;
}
nav{
    background:#eee;
    border-right:1px solid #999;
    bottom:0;
    left:0;
    position:fixed;
    top:0;
    width:300px;
    z-index:1;
}
@media (min-width:801px){
    nav{
        border-left:1px solid #999;
        left:calc((100% - 800px) / 2)
    }
}
nav::before{background:#ecc;bottom:0;content:"";left:0;position:absolute;top:0;width:10px;}
nav::after{background:#999;content:"";height:1px;left:0;position:absolute;right:0;top:99px;}
main{background:#ddf;border-left:1px solid #99c;border-right:1px solid #99c;height:100vh;min-height:100%;margin:0 auto;width:100%;max-width:800px;}
<header>
    <h1><img src="http://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.png?v=9c558ec15d8a"></h1>
    <nav></nav>
</header>
<main></main>
4b9b3361

Ответ 1

В интересах любого, кто сталкивается с этим вопросом и открыт для решения JavaScript, здесь очень простой, который заставляет элемент nav element left на 0, когда ширина окна просмотра больше, чем 800px но ширина элемента body меньше этого.

Недостатки этого решения используют JavaScript для достижения чего-то, что (по-моему, по крайней мере) мы должны иметь возможность делать только с CSS и накладными расходами на использование прослушивателя onresize. Вы можете, однако, удалить этого прослушивателя, если вас беспокоит только правильное расположение меню onload (см. Комментарий в JavaScript в фрагменте).

((b,n,setmenu)=>{
    (setmenu=()=>n.dataset.forceleft=b.offsetWidth<800)();
    window.addEventListener("resize",setmenu,0);
})(document.body,document.querySelector("nav"));

// Use above to set menu position onload and onresize
// Or use below to only set menu position onload
//(d=>d.querySelector("nav").dataset.forceLeft=d.body.offsetWidth<800)(document);
nav{
    background:#eee;
    border-right:1px solid #999;
    bottom:0;
    left:0;
    position:fixed;
    top:0;
    width:300px;
    z-index:1;
}
@media (min-width:801px){
    nav[data-forceleft=false]{
        border-left:1px solid #999;
        left:calc((100% - 800px) / 2)
    }
}
header{
    align-items:center;
    background:#eee;
    border-bottom:1px solid #999;
    display:flex;
    height:100px;
    left:0;
    justify-content:center;
    padding:0 10px;
    position:fixed;
    right:0;
    top:0;
}
h1{
    height:60px;
    position:relative;
    width:calc(100% - 40px);
    max-width:740px;
    z-index:2;
}
img{
    height:100%;
    width:auto;
}
*{box-sizing:border-box;margin:0;padding:0;}
html,body{height:101%;}
nav::before{background:#ecc;bottom:0;content:"";left:0;position:absolute;top:0;width:10px;}
nav::after{background:#999;content:"";height:1px;left:0;position:absolute;right:0;top:99px;}
main{background:#ddf;border-left:1px solid #99c;border-right:1px solid #99c;height:100vh;min-height:100%;margin:0 auto;width:100%;max-width:800px;}
<header>
    <h1><img src="http://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.png?v=9c558ec15d8a"></h1>
    <nav></nav>
</header>
<main></main>

Ответ 2

ИЗМЕНИТЬ здесь все в порядке

/* Alexander Gomez getScrollBarWidth shorten version Josh Bambrick from: 
http://stackoverflow.com/questions/986937/how-can-i-get-the-browsers-scrollbar-sizes 
*/
function getScrollBarWidth() {
  var $outer = $('<div>').css({
      visibility: 'hidden',
      width: 100,
      overflow: 'scroll'
    }).appendTo('body'),
    widthWithScroll = $('<div>').css({
      width: '100%'
    }).appendTo($outer).outerWidth();
  $outer.remove();
  return 100 - widthWithScroll;
};
/* Tested on Chrome 51.0.2704, Firefox 40.0.2, Internet Explorer 11 */
$(document).ready(function() {
  var mydelta = 800; /* your 'main' divs width */
  var delta_mq = mydelta + 1;
  delta = mydelta - getScrollBarWidth();
  var h1_logo = delta - 40;
  var $appended = '<style>h1{max-width:' + h1_logo + 'px} main{max-width:' + mydelta + 'px} @media (min-width:' + delta_mq + 'px){main{left:calc((100% - ' + delta + 'px) / 2);} nav{border-left:1px solid #999;left:calc((100% - ' + delta + 'px) / 2); } }';
  $('body').append($appended);
});
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0
}
/*
     '*' selector is depreciated cause it slow 
     use normalize.css instead 
     
     And i removed your css media and appended them to the 
     page using jquery after getting scrollbar width
     */

header {
  align-items: center;
  background: #eee;
  border-bottom: 1px solid #999;
  display: flex;
  height: 100px;
  left: 0;
  justify-content: center;
  padding: 0 10px;
  position: fixed;
  right: 0;
  top: 0;
}
h1 {
  height: 60px;
  position: relative;
  width: calc(100% - 40px);
  max-width: 750px;
  z-index: 2;
}
img {
  height: 100%;
  width: auto;
}
nav {
  background: #eee;
  border-right: 1px solid #999;
  bottom: 0;
  left: 0;
  position: fixed;
  top: 0;
  width: 300px;
  z-index: 1;
}

main { /* position with 100px top margin */
  position: absolute;
  top: 100px;
}
header { /* chrome fix */
  z-index: 1;
}

nav::before{background:#ecc;bottom:0;content:"";left:0;position:absolute;top:0;width:10px;}
    nav::after{background:#999;content:"";height:1px;left:0;position:absolute;right:0;top:99px;}

main{background:#ddf;border-left:1px solid #99c;border-right:1px solid #99c;height:100vh;min-height:100%;margin:0 auto;width:100%;max-width:800px;}

 
<header>
  <h1 class=logo>
    <img src="http://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.png?v=9c558ec15d8a">
  </h1>
  <nav></nav>
</header>
<main></main>

Ответ 3

Если вы принимаете решения JS... Возможно, вы захотите получить Real Width вместо Scroll Bar Width с помощью следующей функции.

function getRealWidth()
{
    var windowWidth = 0;
    if (typeof(window.innerWidth) == 'number')
   {
        windowWidth = window.innerWidth;
    }
   else
   {
        if (document.documentElement && document.documentElement.clientWidth)
      {
            windowWidth = document.documentElement.clientWidth;
        }
      else
      {
            if (document.body && document.body.clientWidth)
         {
                windowWidth = document.body.clientWidth;
            }
        }
    }

    return windowWidth;
}