42 votes

Positionner l'élément verticalement, absolu horizontalement

Voici ce que j'essaie d'accomplir:

J'ai besoin d'un bouton qui est placé à une certaine distance du côté droit d'un div, et qui est toujours à cette même distance du côté du div, quelle que soit la taille de la fenêtre d'affichage, mais qui défilera avec la fenêtre.

Donc, il est toujours x pixels du côté droit de la div, mais y pixels du haut du port de vue à tout moment.

Est-ce possible?

37voto

ScottS Points 37738

Position De L'Élément Fixe Horizontalement En Fonction D'Un Autre Élément

(Avertissement Remarque: La solution proposée ici n'est pas techniquement "absolue à l'horizontale", comme la question du titre indiqué, mais qui a atteint ce que l'OP voulait, la position fixe de l'élément " X " à distance à partir du bord droit de l'autre, mais fixe dans son défilement verticale.)

J'adore ces types de css défis. Comme une preuve de concept, oui, vous pouvez obtenir ce que vous désirez. Vous pouvez avoir à modifier certaines choses pour vos besoins, mais voici quelques exemples de html et css, qui est passé de FireFox, IE8 et IE7 (IE6, bien sûr, n'ont pas d' position: fixed).

HTML:

<body>
  <div class="inflow">
    <div class="positioner"><!-- may not be needed: see notes below-->
      <div class="fixed"></div>
    </div>
  </div>
</body>

CSS (frontières et de toutes dimensions pour la démonstration):

div.inflow {
  width: 200px; 
  height: 1000px; 
  border: 1px solid blue; 
  float: right; 
  position: relative; 
  margin-right: 100px;
}
div.positioner {position: absolute; right: 0;} /*may not be needed: see below*/
div.fixed {
  width: 80px; 
  border: 1px solid red; 
  height: 100px; 
  position: fixed; 
  top: 60px; 
  margin-left: 15px;
}

La clé est de ne pas mettre la left ou right à l'horizontale sur l' div.fixed mais d'utiliser les deux wrapper divs pour régler la position horizontale. L' div.positioner est pas nécessaire si l' div.inflow est de largeur fixe, comme la marge de gauche de l' div.fixed peut être réglé à connu la largeur du conteneur. Toutefois, si vous désirez que le conteneur d'avoir un pourcentage de la largeur, alors vous aurez besoin de l' div.positioner pour pousser l' div.fixer sur le côté droit de l' div.inflow première.

Edit: il est intéressant de noter, lorsque j'ai mis en overflow: hidden (doit-on besoin de le faire) sur l' div.inflow avaient aucun effet sur la position fixe div être en dehors de l'autre des frontières. Apparemment, la position fixe suffit de le sortir de la div contenant le contexte du overflow.

6voto

Waz Points 138

Je suis arrivé ici à la recherche d'une solution à un problème similaire, qui devait avoir une barre de pied de page qui s'étend sur la largeur de la fenêtre et se trouve en dessous de la variable (hauteur et largeur) de contenu. En d'autres termes, il apparaît que le pied de page est "fixé" par rapport à sa position horizontale, mais qui conserve sa position normale dans le flux de documents à l'égard de sa position verticale. Dans mon cas, j'ai eu le pied de page du texte aligné à droite, si cela a fonctionné pour moi à ajuster dynamiquement la largeur du pied de page. Voici ce que j'ai trouvé:

HTML

<div id="footer-outer">
<div id="footer">
    Footer text.
</div><!-- end footer -->
</div><!-- end footer-outer -->

CSS

#footer-outer
{
    width: 100%;
}
#footer
{
    text-align: right;
    background-color: blue;
    /* various style attributes, not important for the example */
}

CoffeeScript / JavaScript

(À l'aide de prototype.js).

class Footer
document.observe 'dom:loaded', ->
    Footer.width = $('footer-outer').getDimensions().width
Event.observe window, 'scroll', ->
    x = document.viewport.getScrollOffsets().left
    $('footer-outer').setStyle( {'width': (Footer.width + x) + "px"} )

qui compile en:

Footer = (function() {

  function Footer() {}

  return Footer;

})();

document.observe('dom:loaded', function() {
  return Footer.width = $('footer-outer').getDimensions().width;
});

Event.observe(window, 'scroll', function() {
  var x;
  x = document.viewport.getScrollOffsets().left;
  return $('footer-outer').setStyle({
    'width': (Footer.width + x) + "px"
  });
});

Cela fonctionne très bien dans FireFox, et bien en Chrome (c'est un peu de nervosité); je n'ai pas essayé d'autres navigateurs.

Je voulais aussi tout espace de rechange ci-dessous le pied de page pour être d'une autre couleur, j'ai donc ajouté cette footer-stretch div:

HTML

...
</div><!-- end footer -->
<div id="footer-stretch"></div>
</div><!-- end footer-outer -->

CSS

#footer-outer
{
    height: 100%;
}
#footer-stretch
{
    height: 100%;
    background-color: #2A2A2A;
}

Notez que pour le #footer-stretch div de travail, tous les éléments parents jusqu'à l'élément de corps (et éventuellement le code html de l'élément - pas sûr) doit avoir une hauteur fixe (dans ce cas, height = 100%).

3voto

Grinn Points 1966

Après beaucoup de creusement (y compris ce post) je ne pouvais pas trouver une solution que j'ai aimé. La Accepté de Répondre ici n'est pas de faire ce que les OP le titre lu, et la meilleure des solutions que j'ai pu trouver, certes, entraîné dans jumpy éléments. Ensuite, il m'a frappé: Avoir l'élément "fixe", de détecter quand un défilement horizontale se produit, et le mettre à être en position absolue. Voici le code:

Vue comme un Code de Stylo.

HTML

  <div class="blue">
    <div class="red">
    </div>
  </div>

CSS

/* Styling */
.blue, .red {
  border-style: dashed;
  border-width: 2px;
  padding: 2px;
  margin-bottom: 2px;
}

/* This will be out "vertical-fixed" element */
.red {
  border-color: red;
  height: 120px;
  position: fixed;
  width: 500px;
}

/* Container so we can see when we scroll */
.blue {
  border-color: blue;
  width: 50%;
  display: inline-block;
  height: 800px;
}

JavaScript

$(function () {
  var $document = $(document),
      left = 0,
      scrollTimer = 0;

  // Detect horizontal scroll start and stop.
  $document.on("scroll", function () {
    var docLeft = $document.scrollLeft();
    if(left !== docLeft) {
      var self = this, args = arguments;
      if(!scrollTimer) {
        // We've not yet (re)started the timer: It's the beginning of scrolling.
        startHScroll.apply(self, args);
      }
      window.clearTimeout(scrollTimer);
      scrollTimer = window.setTimeout(function () {
        scrollTimer = 0;
        // Our timer was never stopped: We've finished scrolling.
        stopHScroll.apply(self, args);
      }, 100);
      left = docLeft;
    }
  });

  // Horizontal scroll started - Make div's absolutely positioned.
  function startHScroll () {
    console.log("Scroll Start");
    $(".red")
    // Clear out any left-positioning set by stopHScroll.
    .css("left","")
    .each(function () {
      var $this = $(this),
          pos = $this.offset();
      // Preserve our current vertical position...
      $this.css("top", pos.top)
    })
    // ...before making it absolutely positioned.
    .css("position", "absolute");
  }

  // Horizontal scroll stopped - Make div's float again.
  function stopHScroll () {
    var leftScroll = $(window).scrollLeft();
    console.log("Scroll Stop");
    $(".red")
    // Clear out any top-positioning set by startHScroll.
    .css("top","")
    .each(function () {
      var $this = $(this), 
        pos = $this.position();
      // Preserve our current horizontal position, munus the scroll position...
      $this.css("left", pos.left-leftScroll);
    })
    // ...before making it fixed positioned.
    .css("position", "fixed");
  }
});

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by: