Centrage horizontal CSS d'un div fixe?

183
#menu {
    position: fixed;
    width: 800px;
    background: rgb(255, 255, 255); /* The Fallback */
    background: rgba(255, 255, 255, 0.8);
    margin-top: 30px;
}

Je sais que cette question est un million de fois là-bas, mais je ne trouve pas de solution à mon cas. J'ai un div, qui devrait être fixé sur l'écran, même si la page défile, elle doit toujours rester CENTRÉE au milieu de l'écran!

Le div doit avoir une 500pxlargeur, doit être 30pxéloigné du haut (marge en haut), doit être centré horizontalement au milieu de la page pour toutes les tailles de navigateur et ne doit pas bouger lors du défilement du reste de la page.

Est-ce possible?

mat
la source

Réponses:

167
left: 50%;
margin-left: -400px; /* Half of the width */
Quentin
la source
26
cela ne fonctionne pas comme prévu lorsque vous redimensionnez la fenêtre du navigateur.
3
@Bahodir: Êtes-vous sûr? Il me semble juste lors du redimensionnement. Je pense que cela -400est dû à la largeur de la div définie 800.
Merlyn Morgan-Graham
1
@PrestonBadeer - Comme celui sur lequel porte la question?
Quentin
3
Tout à fait d'accord - ce n'est PAS une solution! Ne codez jamais quelque chose de cette manière. -1
Nate I
3
J'ai rejeté cette proposition NON parce que c'était une mauvaise réponse pour son époque - c'était une bonne réponse, mais parce qu'elle ne l'est plus, et la réponse la plus élevée a besoin de toute l'aide qu'elle peut obtenir pour être considérée comme la meilleure réponse MAINTENANT. Quentin: Je pense que ce serait une bonne idée d'éditer un commentaire à cet effet dans la réponse elle-même - j'inverserais alors mon vote négatif.
Nick Rice
547

Les réponses ici sont dépassées. Vous pouvez maintenant facilement utiliser une transformation CSS3 sans coder en dur une marge . Cela fonctionne sur tous les éléments, y compris les éléments sans largeur ni largeur dynamique.

Centre horizontal:

left: 50%;
transform: translateX(-50%);

Centre vertical:

top: 50%;
transform: translateY(-50%);

À la fois horizontal et vertical:

left: 50%;
top: 50%;
transform: translate(-50%, -50%);

La compatibilité n'est pas un problème: http://caniuse.com/#feat=transforms2d

Maciej Krawczyk
la source
87
+1 Cette réponse démontre un problème avec le stackoverflow: les anciennes réponses qui étaient bonnes pour leur journée et qui ont été acceptées à juste titre peuvent être fièrement au-dessus, donnant l'impression qu'elles sont toujours appropriées, tandis que les bonnes réponses pour un monde plus récent, comme celui-ci, doivent se frayer un chemin contre toute attente.
Nick Rice
11
@NickRice 100% d'accord. Cette réponse devrait être la nouvelle réponse acceptée. Les développeurs juniors ne devraient même pas voir la réponse actuellement acceptée!
Nate I
2
@matt, veuillez accepter celui-ci à la place. Faites défiler de très loin pour voir cela.
ssbb
4
Cela crée des effets de flou dans l'ombre de boîte dans les éléments de contenu.
rab
4
Oui, Chrome ne brouille pas correctement le contenu transformé. Le texte est également flou. Mais c'est la seule solution pour avoir un élément fixe centré sans codage en dur et en utilisant des éléments wrapper. Si vous ne vous souciez pas des événements de pointeur de l'arrière-plan, vous pouvez obtenir le même effet avec un wrapper plein écran et une flexbox, ou la solution de @ salomvary ci-dessous.
Maciej Krawczyk
58

Si l'utilisation de blocs en ligne est une option, je recommanderais cette approche:

.container { 
    /* fixed position a zero-height full width container */
    position: fixed;
    top: 0; /* or whatever position is desired */
    left: 0;
    right: 0;
    height: 0;
    /* center all inline content */
    text-align: center;
}

.container > div {
    /* make the block inline */
    display: inline-block;
    /* reset container's center alignment */
    text-align: left;
} 

J'ai écrit un court article à ce sujet ici: http://salomvary.github.com/position-fixed-horizontally-centered.html

salomvary
la source
1
10x, cela a très bien fonctionné pour moi sans avoir à coder en dur des nombres pour widthou quelque chose - contrairement à la réponse
@Quentins
30

Edit septembre 2016: Bien que ce soit bien d'avoir encore un vote positif occasionnel pour cela, parce que le monde a évolué, j'irais maintenant avec la réponse qui utilise la transformation (et qui a une tonne de votes positifs). Je ne ferais plus ça de cette façon.

Une autre façon de ne pas avoir à calculer une marge ou d'avoir besoin d'un sous-conteneur:

#menu {
    position: fixed;   /* Take it out of the flow of the document */
    left: 0;           /* Left edge at left for now */
    right: 0;          /* Right edge at right for now, so full width */ 
    top: 30px;         /* Move it down from top of window */
    width: 500px;      /* Give it the desired width */ 
    margin: auto;      /* Center it */
    max-width: 100%;   /* Make it fit window if under 500px */ 
    z-index: 10000;    /* Whatever needed to force to front (1 might do) */
}
Nick Rice
la source
@Joey Que fait le fond: 0? c'est-à-dire pourquoi est-il nécessaire? (Il y a quelque temps que j'ai regardé ça!)
Nick Rice
bottom:0garantirait que le menu est toujours centré verticalement, mais je vois maintenant que ce n'est pas ce que l'OP a demandé. :)
Jordan H
J'ai essayé de l'utiliser dans un contexte différent parce que j'ai compris qu'il ne se
centrait
Parce que le monde a évolué, j'irais maintenant avec la réponse qui utilise la transformation. (J'ai déjà fait ce commentaire, faisant référence au nom utilisé par le répondeur - mais ils ont changé ce nom pour que mon commentaire n'ait plus de sens et je l'ai supprimé - il suffit de rechercher sur cette page pour transformer à la place.)
Nick Rice
7

Il est possible de centrer horizontalement la div de cette façon:

html:

<div class="container">
    <div class="inner">content</div>
</div>

css:

.container {
    left: 0;
    right: 0;
    bottom: 0; /* or top: 0, or any needed value */
    position: fixed;
    z-index: 1000; /* or even higher to prevent guarantee overlapping */
}

.inner {
    max-width: 600px; /* just for example */
    margin: 0 auto;
}

En utilisant de cette façon, vous aurez toujours votre bloc intérieur centré, en plus il peut être facilement transformé en vrai responsive (dans l'exemple, il sera juste fluide sur des écrans plus petits), donc pas de limitation comme dans l'exemple de question et dans la réponse choisie .

Denis V
la source
5

... ou vous pouvez envelopper votre menu div dans un autre:

    <div id="wrapper">
       <div id="menu">
       </div>
    </div>


#wrapper{
         width:800px;
         background: rgba(255, 255, 255, 0.8);
         margin:30px auto;
         border:1px solid red;
    }

    #menu{
        position:fixed;
        border:1px solid green;
        width:300px;
        height:30px;
    }
Meduza
la source
5

Voici une autre solution à deux div. J'ai essayé de le garder concis et non codé en dur. Tout d'abord, le HTML attendu:

<div id="outer">
  <div id="inner">
    content
  </div>
</div>

Le principe derrière le css suivant est de positionner un côté de "externe", puis d'utiliser le fait qu'il suppose la taille de "interne" pour décaler relativement ce dernier.

#outer {
  position: fixed;
  left: 50%;          // % of window
}
#inner {
  position: relative;
  left: -50%;         // % of outer (which auto-matches inner width)
}

Cette approche est similaire à celle de Quentin, mais l'intérieur peut être de taille variable.

Anonyme
la source
-1

Voici une solution flexbox lors de l'utilisation d'un div wrapper plein écran. justify-content centre son div enfant horizontalement et align-items le centre verticalement.

<div class="full-screen-wrapper">
    <div class="center"> //... content</div>
</div>

.full-screen-wrapper { 
  position: fixed;
  display: flex;
  justify-content: center;
  width: 100vw;
  height: 100vh;
  top: 0;
  align-items: center;
}

.center {
  // your styles
}
Vien Tang
la source