CSS: réglage de la largeur / hauteur en pourcentage moins les pixels

J'ai vu cette question posée dans quelques autres contextes sur SO, mais j'ai pensé que cela valait la peine de demander à nouveau pour mon cas particulier. J'essaie de créer des classes CSS réutilisables pour plus de cohérence et moins d'encombrement sur mon site, et je suis coincé à essayer de normaliser une chose que j'utilise fréquemment.

J'ai un Div de conteneur pour lequel je ne veux pas définir la hauteur (car il variera en fonction de l'endroit où il se trouve sur le site), et à l'intérieur il y a un div d'en-tête, puis un div non ordonné liste des éléments, tous avec CSS appliqué à eux. Cela ressemble beaucoup à ceci:

Widget

Je veux que la liste non ordonnée occupe la place restante dans le conteneur div, sachant que l'en-tête div est de 18px. Je ne sais pas comment spécifier la hauteur de la liste comme "le résultat de 100% moins 18px". Quelqu'un aurait-il des conseils dans cette situation?

403
demandé sur Martijn Pieters 2010-03-12 20:34:54

11 réponses

Je me rends compte que c'est un ancien post, mais étant donné qu'il n'a pas été suggéré, il convient de mentionner que si vous écrivez pour des navigateurs compatibles CSS3, vous pouvez utiliser calc:

height: calc(100% - 18px);

Il vaut la peine de noter que tous les navigateurs ne supportent pas actuellement la fonction CSS3 calc() standard, donc l'implémentation des versions spécifiques au navigateur de la fonction peut être requise comme suit:

/* Firefox */
height: -moz-calc(100% - 18px);
/* WebKit */
height: -webkit-calc(100% - 18px);
/* Opera */
height: -o-calc(100% - 18px);
/* Standard */
height: calc(100% - 18px);
753
répondu Levi Botelho 2017-06-16 11:31:29

Pour une approche un peu différente, vous pouvez utiliser quelque chose comme ceci sur la liste:

position: absolute;
top: 18px;
bottom: 0px;
width: 100%;

Cela fonctionne tant que le conteneur parent a position: relative;

66
répondu Nicolas Galler 2012-11-02 07:36:21

J'utilise Jquery pour cela

function setSizes() {
   var containerHeight = $("#listContainer").height();
   $("#myList").height(containerHeight - 18);
}

Ensuite, je lie le redimensionnement de la fenêtre pour le recalcer chaque fois que la fenêtre du navigateur est redimensionnée (si la taille du conteneur a changé avec le redimensionnement de la fenêtre)

$(window).resize(function() { setSizes(); });
22
répondu puffpio 2010-03-12 18:56:05

Ne définissez pas la hauteur en pourcentage, définissez simplement les top=0 et bottom=0, comme ceci:

#div {
   top: 0; bottom: 0;
   position: absolute;
   width: 100%;
}
14
répondu kaleazy 2012-08-01 17:16:12

En Supposant 17px en-tête hauteur de

Liste css:

height: 100%;
padding-top: 17px;

En-tête css:

height: 17px;
float: left;
width: 100%;
8
répondu ghoppe 2010-03-12 19:03:15
  1. Utilisez des marges négatives sur l'élément que vous souhaitez moins de pixels. (élément désiré)
  2. Faire overflow:hidden; sur l'élément contenant
  3. passez à overflow:auto; sur l'élément désiré.

Ça a marché pour moi!

7
répondu desbest 2011-08-30 15:03:48

Essayez box-sizing. Pour la liste:

height: 100%;
/* Presuming 10px header height */
padding-top: 10px;
/* Firefox */
-moz-box-sizing: border-box;
/* WebKit */
-webkit-box-sizing: border-box;
/* Standard */
box-sizing: border-box;

Pour l'en-tête:

position: absolute;
left: 0;
top: 0;
height: 10px;

Bien sûr, le conteneur parent devrait avoir quelque chose comme:

position: relative;
5
répondu Light 2014-06-30 12:27:09

J'ai essayé certaines des autres réponses, et aucune d'entre elles n'a fonctionné comme je le voulais. Notre situation était très similaire où nous avions un en-tête de fenêtre et la fenêtre était redimensionnable avec des images dans le corps de la fenêtre. Nous voulions verrouiller le rapport d'aspect du redimensionnement sans avoir besoin d'ajouter des calculs pour tenir compte de la taille fixe de l'en-tête et avoir toujours l'image remplir le corps de la fenêtre.

Ci-dessous, j'ai créé un extrait très simple qui montre ce que nous avons fini par faire qui semble fonctionner Eh bien pour notre situation et devrait être compatible avec la plupart des navigateurs.

Sur notre élément de fenêtre, nous avons ajouté une marge de 20px qui contribue au positionnement par rapport aux autres éléments de l'écran, mais ne contribue pas à la "taille" de la fenêtre. L'en-tête de fenêtre est alors positionné absolument (ce qui le supprime du flux d'autres éléments, de sorte qu'il ne provoquera pas le déplacement d'autres éléments comme la liste non ordonnée) et son sommet est positionné-20px qui place l'en-tête à l'intérieur du marge de la fenêtre. Enfin, notre élément ul est ajouté à la fenêtre, et la hauteur peut être réglée à 100%, ce qui le fera remplir le corps de la fenêtre (à l'exclusion de la marge).

*,*:before,*:after
{
  box-sizing: border-box;
}

.window
{
  position: relative;
  top: 20px;
  left: 50px;
  margin-top: 20px;
  width: 150px;
  height: 150px;
}

.window-header
{
  position: absolute;
  top: -20px;
  height: 20px;
  border: 2px solid black;
  width: 100%;
}

ul
{
  border: 5px dashed gray;
  height: 100%;
}
<div class="window">
  <div class="window-header">Hey this is a header</div>
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
  </ul>
</div>
2
répondu TJ Rockefeller 2016-04-28 14:00:23

Merci, j'ai résolu le mien avec votre aide, en le peaufinant un peu puisque je veux une div 100% width 100% heigth (moins de hauteur d'une barre inférieure) et pas de défilement sur le corps (sans pirater / Cacher les barres de défilement).

Pour CSS:

 html{
  width:100%;height:100%;margin:0px;border:0px;padding:0px;
 }
 body{
  position:relative;width:100%;height:100%;margin:0px;border:0px;padding:0px;
 }
 div.adjusted{
  position:absolute;width:auto;height:auto;left:0px;right:0px;top:0px;bottom:36px;margin:0px;border:0px;padding:0px;
 }
 div.the_bottom_bar{
  width:100%;height:31px;margin:0px;border:0px;padding:0px;
}

Pour HTML:

<body>
<div class="adjusted">
 // My elements that go on dynamic size area
 <div class="the_bottom_bar">
  // My elements that goes on bottom bar (fixed heigh of 31 pixels)
 </div>  
</div>  

Cela a fait l'affaire, oh oui j'ai mis une valeur little greatter sur div.ajusté pour le bas que pour la hauteur de la barre inférieure, sinon la barre de défilement verticale apparaît, j'ai ajusté pour être la valeur la plus proche.

Cette différence est due au fait que l'un des éléments sur la zone dynamique ajoute un trou de fond supplémentaire que je ne sais pas comment se débarrasser de... c'est une balise vidéo (HTML5), veuillez noter que je mets cette balise vidéo avec ce css (donc il n'y a aucune raison pour qu'elle fasse un trou inférieur, mais c'est le cas):

 video{
  width:100%;height:100%;margin:0px;border:0px;padding:0px;
 }

L'objetive: avoir une vidéo qui prend le 100% du navigateur (et redimensionne dynamiquement lorsque le navigateur est redimensionné, mais sans modifier le rapport d'aspect) moins un espace inférieur que j'utilise pour un div avec quelques textes, boutons, etc (et validateurs w3c & css bien sûr).

EDIT: j'ai trouvé la raison, la balise vidéo est comme du texte, pas un élément de bloc, donc je l'ai corrigé avec ce css:

 video{
  display:block;width:100%;height:100%;margin:0px;border:0px;padding:0px;
 }

Notez l' display:block; sur la balise vidéo.

1
répondu Claudio 2016-05-13 12:10:07

Une Autre façon d'atteindre le même objectif: flex boîtes. Faites du conteneur une boîte flexible de colonne, puis vous avez toute la liberté de permettre à certains éléments d'avoir une taille fixe (comportement par défaut) ou de remplir/rétrécir jusqu'à l'espace du conteneur (avec flex-grow:1 et flex-shrink:1).

#wrap {        
  display:flex;
  flex-direction:column;
}
.extendOrShrink {
  flex-shrink:1;
  flex-grow:1;
  overflow:auto;
}

Voir https://jsfiddle.net/2Lmodwxk/ (essayez d'étendre ou de réduire la fenêtre pour remarquer l'effet)

REMARQUE: Vous pouvez également utiliser la propriété abrégée:

   flex:1 1 auto;
1
répondu tarulen 2018-06-24 22:18:13

Je ne suis pas sûr si cela fonctionne dans votre situation particulière, mais j'ai trouvé que le remplissage sur le div intérieur poussera le contenu à l'intérieur d'un div si le div contenant est une taille fixe. Vous devrez soit flotter ou positionner absolument votre élément d'en-tête, mais sinon, je n'ai pas essayé cela pour les divs de taille variable.

0
répondu dclowd9901 2010-03-12 19:05:26