Si un élément est défini sur width: 100vw;
et il y a une barre de défilement verticale, la largeur de l'élément sera égale à la fenêtre d'affichage 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? Mis à part changer mon css/balisage pour rendre l'élément 100% de la largeur du corps, je ne pense à rien.
Testé dans Chrome Version 43.0.2357.81 m & FF 36.0.1 & Opera 20.0.1387.91 sur Windows 8.1
Voici le code demandé:
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;
}
Fondamentalement, la réponse est non, si vous avez une barre de défilement verticale, il n'y a aucun moyen de faire 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 qu'un élément ait une largeur de 100% de la fenêtre visible (barre de défilement de la fenêtre de visualisation), vous devrez le définir à 100% du corps. Vous ne pouvez pas le faire avec des unités vw s'il y a une barre de défilement verticale.
1. Définissez tous les éléments ancêtres pour qu'ils soient statiques
Si vous vous assurez que tous les ancêtres de .box
Sont définis sur position: static;
, Définissez .box
Sur width: 100%;
Pour que ce soit 100% de la largeur du corps . Ce n'est cependant pas toujours possible. Parfois, vous avez besoin que l'un des ancêtres soit position: absolute;
Ou position: relative;
.
2. Déplacer l'élément en dehors des ancêtres non statiques
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 régler l'élément à 100% de la largeur du corps.
3. Supprimer la barre de défilement verticale
Si vous n'avez pas besoin du défilement vertical, vous pouvez simplement supprimer la barre de défilement verticale en définissant l'élément <html>
Sur overflow-y: hidden;
.
4. Supprimer la barre de défilement horizontale Cela ne résout pas le problème, mais peut convenir à certaines situations.
La définition de l'élément <html>
Sur overflow-y: scroll; overflow-x: hidden;
Empêchera la barre de défilement horizontale d'apparaître, mais l'élément 100vw débordera toujours.
Spécification des longueurs de pourcentage de fenêtre
Les longueurs en pourcentage de la fenêtre sont relatives à la taille du bloc contenant initial. Lorsque la hauteur ou la largeur du bloc contenant initial est modifiée, elles sont mises à l'échelle en conséquence. Cependant, lorsque la valeur de débordement sur l'élément racine est auto, toutes les barres de défilement sont supposées ne pas exister. Notez que la taille initiale du bloc contenant est affectée par la présence de barres de défilement dans la fenêtre.
Il semble qu'il y ait un bogue car les unités vw ne doivent inclure la largeur de la barre de défilement que lorsque le débordement 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 cela n'a pas changé.
Je sais que c'est une vieille question, mais le bogue existe toujours dans les navigateurs modernes. Je n'aimais pas l'idée de faire overflow-x: hidden
C'est donc 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
Du montant 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 une définition avec donc je devais également déclarer la marge.
Quelques notes concernant le code ci-dessous: tout d'abord, j'ai remarqué que 20px semble être un nombre magique assez 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 rechange.
De plus, cela ne signifie pas garantie qu'il n'y aura jamais de barres de défilement. Puisqu'il nécessite Javascript, les utilisateurs qui ne l'ont pas activé verront des barres de défilement horizontales. Vous pouvez contourner cela en définissant overflow-x: hidden
, Puis en ajoutant une classe pour la remplacer lors de l'exécution de Javascript.
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));
}
}
}
Ensuite, 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();
En remarque, 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
Les rembourrages et les bordures peuvent interférer. Il en va de même pour la marge. Utilisez dimensionnement de la boîte pour calculer la largeur en incluant 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 redistribution qui fait apparaître la barre de défilement après le calcul initial de la largeur de la fenêtre d'affichage. Cela ne semble pas se produire dans les navigateurs sans barre de défilement interférente (iOS, OS X, IE 11 Metro), mais peut affecter tous les autres navigateurs.
Je me débattais également avec cela, et je pensais aussi aux variables CSS comme la solution. Les variables CSS ne sont pas prises en charge dans IE11, alors j'ai essayé autre chose:
Je l'ai corrigé en calculant la largeur de la barre de défilement: en soustrayant la largeur de body
(sans barre de défilement) de la largeur de window
(y compris la barre de défilement). Je l'utilise pour l'ajouter au 100% du corps, voir la variable plusScrollBar
.
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 ça: il faut considérer que toutes les barres de défilement n'ont pas la même largeur ou ne sont pas du tout considérées comme de l'espace conservé. :)
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%));
}