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é:
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;
}
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;
.
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.
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;
.
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.
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.
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
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.
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%));
}
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é. :)
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);
}
J'ai corrigé cela sur mon site en ajoutant body{overflow-x:hidden} à la page en question.
Fonctionne aussi sur votre exemple.
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/