Empêcher 100vw de créer défilement horizontal

Si un élément est défini sur width: 100vw; et qu'il existe une barre de défilement verticale, la largeur de l'élément sera égale à la fenêtre plus la largeur de la barre de défilement.

Est - il possible d'empêcher cela?

Est-il possible d'empêcher cela sans désactiver le défilement horizontal sur toute la page? En plus de changer mon CSS / balisage pour rendre l'élément 100% de la largeur du corps, Je ne peux penser à rien.

testé dans la version Chrome 43.0.2357.81 m & FF 36.0.1 & Opera 20.0.1387.91 sous Windows 8.1

Voici le code demandé:

Exemple

Html

<div class="parent">
    <div class="box"></div>
</div>
<div class="tall"></div>

Css

body { margin: 0; }
html { box-sizing: border-box; }
*, *::before, *::after {
    box-sizing: inherit;
    position: relative;
}
.parent {
    background: rgba(0, 0, 0, .4);
    height: 100px;
    width: 5rem;
    margin-bottom: 25px;
}

.box {
    position: absolute;
    top: 0;
    left: 0;
    background: rgba(0, 0, 0, .4);
    height: 50px;
    width: 100vw;
}

.tall {
    height: 100rem;
}
27
demandé sur Hal Carleton 2015-05-27 20:45:03

8 réponses

Fondamentalement, la réponse est non, si vous avez une barre de défilement verticale, il n'y a aucun moyen de rendre 100vw égal à la largeur de la fenêtre visible. Voici les solutions que j'ai trouvées pour ce problème.

Avertissement: je n'ai pas testé ces solutions pour la prise en charge du navigateur


Tl;dr

Si vous avez besoin d'un élément à 100% de la largeur de la fenêtre visible (fenêtre moins la barre de défilement), vous devrez le définir à 100% du corps. Vous ne pouvez pas faites-le avec des unités vw s'il y a une barre de défilement verticale.


1. Définissez tous les éléments ancêtres sur la position statique

Si vous vous assurez que tous les ancêtres de .box sont définis sur position: static;, alors définissez .box sur width: 100%; afin que ce soit 100% de la largeur du corps. Ce n'est pas toujours possible. Parfois, vous avez besoin d'un des ancêtres pour être position: absolute; ou position: relative;.

Exemple

2. Déplacer l'élément en dehors de non-statique ancêtres

Si vous ne pouvez pas définir les éléments ancêtres sur position: static;, vous devrez déplacer .box en dehors d'eux. Cela vous permettra de définir l'élément à 100% de la largeur du corps.

Exemple

3. Supprimer La Barre De Défilement Verticale

Si vous n'avez pas besoin de défilement vertical, vous pouvez simplement supprimer la barre de défilement verticale en définissant l'élément <html> sur overflow-y: hidden;.

Exemple

4. Supprimer Horizontale Barre de défilement cela ne résout pas le problème, mais peut convenir à certaines situations.

Définir l'élément <html> sur {[11] } empêchera la barre de défilement horizontale d'apparaître, mais l'élément 100vw débordera toujours.

Exemple

Fenêtre D'Affichage De Pourcentage Longueurs Spec

Les longueurs en pourcentage de la fenêtre d'affichage sont relatives à la taille bloc contenant initial. Lorsque la hauteur ou la largeur de l'initiale le bloc contenant est modifié, ils sont mis à l'échelle en conséquence. Cependant, lorsque la valeur de débordement sur l'élément racine est automatique, tout de défilement les barres sont supposées ne pas exister. Notez que l'initiale contenant la taille du bloc est affectée par la présence de barres de défilement sur le fenêtre d'affichage.

Il semble qu'il y ait un bug car les unités vw ne devraient inclure la largeur de la barre de défilement que lorsque overflow est défini sur auto sur l'élément racine. Mais j'ai essayé de définir l'élément racine sur overflow: scroll; et c'est arrivé pas de changement.

Exemple

19
répondu Hal Carleton 2018-07-16 15:18:38

Je sais que c'est une vieille question, mais le bug existe toujours dans les navigateurs modernes. Je n'aimais pas l'idée de faire {[2] } donc c'est ce que j'ai fait. Un exemple complet est disponible ici: http://codepen.io/bassplayer7/pen/egZKpm

Mon approche consistait à déterminer la largeur de la barre de défilement et à utiliser calc() pour réduire le 100vw de la quantité de la barre de défilement. C'est un peu plus compliqué parce que dans mon cas, je tirais la largeur du contenu d'une boîte qui avait défini avec j'ai donc besoin de déclarer la marge.

Quelques notes concernant le code ci-dessous: tout d'abord, j'ai remarqué que 20px semble être un nombre magique plutôt large pour les barres de défilement. J'utilise une variable SCSS (elle ne doit pas nécessairement être SCSS) et du code en dehors de @supports comme solution de secours.

En outre, cela ne garantit pas {[17] } qu'il n'y aura jamais de barres de défilement. Comme il nécessite Javascript, les utilisateurs qui ne l'ont pas activé verront des barres de défilement horizontales. Vous pourriez contourner cela en définir overflow-x: hidden, puis Ajouter une classe pour le remplacer lorsque Javascript s'exécute.

Code Complet:

$scroll-bar: 20px;

:root {
    --scroll-bar: 8px;
}

.screen-width {
  width: 100vw;
  margin: 0 calc(-50vw + 50%);

    .has-scrollbar & {
        width: calc(100vw - #{$scroll-bar});
        margin: 0 calc(-50vw + 50% + #{$scroll-bar / 2});
    }

    @supports (color: var(--scroll-bar)) {
        .has-scrollbar & {
            width: calc(100vw - var(--scroll-bar));
            margin: 0 calc(-50vw + 50% + (var(--scroll-bar) / 2));
        }
    }
}

Alors ce Javascript définira la propriété personnalisée CSS:

function handleWindow() {
    var body = document.querySelector('body');

    if (window.innerWidth > body.clientWidth + 5) {
        body.classList.add('has-scrollbar');
        body.setAttribute('style', '--scroll-bar: ' + (window.innerWidth - body.clientWidth) + 'px');
    } else {
        body.classList.remove('has-scrollbar');
    }
}

handleWindow();

Comme note de côté, les utilisateurs de Mac peuvent tester cela en allant dans Préférences Système - > Général - > afficher les barres de défilement = toujours

4
répondu bassplayer7 2017-01-12 14:36:01

Les rembourrages et les bordures peuvent interférer. Donc peut de marge. Utilisez box-sizing pour calculer la largeur, y compris ces attributs. Et peut-être supprimer la marge (le cas échéant) de la largeur.

* {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}
body {
    margin: 0; /* interferes with 100vw */
}
.parent {
    width: 100vw;
    max-width: 100%; /* see below */
}
.box {
    width: 100%; /* For those good old-fashioned browsers with no vw or calc() support */
    width: -webkit-calc(100vw - [your horizontal margin, if any]);
    width: -moz-calc(100vw - [your horizontal margin, if any]);
    width: calc(100vw - [your horizontal margin, if any]);
    max-width: 100%
}

Il semble que vous deviez ajouter max-width: 100%; s'il y a une refusion qui fait apparaître la barre de défilement après le calcul initial de la largeur de la fenêtre. Cela ne semble pas se produire dans les navigateurs sans une barre de défilement interférant (iOS, OS X, IE 11 Metro), mais peut affecter tous les autres navigateurs.

2
répondu Niklas Brunberg 2015-05-27 19:08:10

Voici ma solution au problème de 100vw en ajoutant un défilement horizontal:

html {
width: calc(100% + calc(100vw - 100%));
overflow-x: hidden;
}

.box {
width: calc(100% + calc(100vw - 100%));
}
2
répondu moy2010 2017-09-09 22:18:54

J'étais aussi aux prises avec cela, et j'ai aussi pensé aux variables CSS comme solution. Les variables CSS ne sont pas supportées dans IE11, donc j'ai essayé autre chose:

Je l'ai corrigé en calculant la largeur de la barre de défilement: en soustrayant la largeur de la body (non compris la barre de défilement) de la largeur de la window (y compris la barre de défilement). Je l'utilise pour l'ajouter au 100% du corps, voir plusScrollBar variable.

JS:

    // calculate width of scrollbar and add it as inline-style to the body
var checkScrollBars = function() {
    var b = $('body');
    var normalw = 0;
    var scrollw = 0;
    normalw = window.innerWidth;
    scrollw = normalw - b.width();

    var plusScrollBar = 'calc(' + '100% + ' + scrollw + 'px)'
    document.querySelector('body').style.minWidth = plusScrollBar;
}();

CSS:

html{
    overflow-x: hidden;
}

Pourquoi j'aime ceci: Il prend en considération que toutes les barres de défilement ne sont pas de la même largeur ou considérées comme un espace conservé. :)

1
répondu Cyd 2017-12-05 15:54:27

Voici ce que je fais:

div.screenwidth{
    width:100%;  /* fallback for browsers that don't understand vw or calc */
    width: calc(100vw - 17px); /* -17 because vw is calculated without the scrollbar being considered & 17px is width of scrollbars */
    position:relative;  /* use this if the parent div isn't flush left */
    right: calc((100vw - 17px - 100% )/2);

}

-1
répondu innocuous_name 2015-10-08 14:53:15

J'ai corrigé cela sur mon site en ajoutant body{overflow-x:hidden} à la page en question.

Fonctionne aussi sur votre exemple.

-1
répondu Adam 2016-03-17 23:40:14

Un élément avec width: 100vw provoque uniquement des barres de défilement horizontales lorsque l'un de ses parents a un remplissage horizontal. Sinon il doit s'intègrent bien.

Vérifiez ce violon: http://jsfiddle.net/1jh1cybc/ le .parent2 a un remplissage, ce qui fait sortir le .box interne de sa largeur parente.

Modifier:

, Dans votre cas, je suppose que votre body a une marge. Vérifiez ce violon avec votre code et essayez de supprimer la règle CSS body: http://jsfiddle.net/1jh1cybc/1/

-2
répondu redelschaap 2015-05-27 18:41:34