Placer l'insigne sur le coin de l'image automatiquement

j'ai une mise en page où les images" flottent " dans une certaine zone. La disposition ressemble à ceci:

Layout Example

La source comme ceci:

<div class="free_tile">
  <a class="img_container canonical" href="/photos/10">
    <img class="canonical" src="http://s3.amazonaws.com/t4e-development/photos/1/10/andrew_burleson_10_tile.jpg?1303238025" alt="Andrew_burleson_10_tile">
    <!-- EDIT: I am aware that I can put the badge here. See the edit notes and image below. -->
  </a>
  <div class="location">Houston</div>
  <div class="taxonomy"> T6 | Conduit | Infrastructure </div>
</div>

Le CSS ressemble à ceci (SCSS):

div.free_tile { width: 176px; height: 206px; float: left; margin: 0 20px 20px 0; position: relative;
  &.last { margin: 0 0 20px 0; }
  a.img_container { display: block; width: 176px; height: 158px; text-align: center; line-height: 156px; margin-bottom: 10px; }
  img { margin: 0; border: 1px solid $dark3; display: inline-block; vertical-align: middle; @include boxShadow;
    &.canonical { border: 1px solid $transect; }
  }
  .location, .taxonomy { width: 176px; }
  .location { font-weight: 700; }
  .taxonomy { line-height: 10px; font-size: 10px; text-transform: uppercase; height: 20px; overflow: hidden; }
}
div.transect_badge { height: 20px; width: 20px; background: url('/images/transect-badge.png'); }

donc, fondamentalement les images sont assises verticalement alignées centre et texte aligné centre, et ils ont une largeur maximale de 176 et hauteur maximale de 158, mais ils sont recadrés à maintenir le ratio d'aspect original, le vrai haut à droite de chaque image tombe différemment selon l'image qu'il est.

j'ai un badge que j'aimerais mettre dans le coin de certaines images (lorsque l'image est "canonique"). Vous voyez le style ci-dessus ( div.transect_badge ).

le problème, bien sûr, est que je ne sais pas où le coin supérieur de l'image sera donc je ne peux pas hardcode la position via CSS.

je suppose que Je vais devoir le faire par jQuery ou quelque chose comme ça. Donc, j'ai commencé avec une méthode jQuery pour ajouter automatiquement le badge div à toutes les images canoniques. Ça marche très bien, mais je ne sais pas comment le positionner dans le coin supérieur gauche.

Comment faire? (idéalement en utilisant juste HTML et CSS, mais de façon réaliste en utilisant JS / jQuery)

--EDIT-- Voici le problème: l'image flotte à l'intérieur d'un conteneur, donc le coin du l'image peut tomber n'importe où à l'intérieur des limites extérieures du contenant. Voici un exemple de ce qui se passe si j'essaie d'utiliser position:absolute; top:0; left:0 dans le même conteneur que l'image est liée par: The problem

16
demandé sur Andrew 2011-05-22 00:34:04

4 réponses

Il a fallu quelques essais, mais ici il est: la indépendants de la taille de l'image de l'insigne positionneur .

HTML:

<div class="tile">
    <span class="photo">
        <a href=""><img src="/photos/10.jpg" alt="10" /><ins></ins></a>
    </span>
    <p class="location">Houston</p>
    <p class="taxonomy">T6 | Conduit | Infrastructure</p>        
</div>

CSS:

.tile {
    float: left;
    width: 176px;
    height: 206px;
    margin: 0 20px 20px 0;
 }
.photo {
    display: block;
    width: 176px;
    height: 158px;
    text-align: center;
    line-height: 158px;
    margin-bottom: 10px;
}
a {
    display: inline-block;
    position: relative;
    line-height: 0;
}
img {
    border: none;
    vertical-align: middle;
}
ins {
    background: url('/images/badge.png') no-repeat 0 0;
    position: absolute;
    left: 0;
    top: 0;
    width: 20px;
    height: 20px;
}

exemple:

dans les tentatives précédentes moins réussies (voir éditer l'histoire), le problème était d'obtenir l'image verticalement centrée et d'obtenir son parent la même taille (afin de placez l'insigne dans le coin supérieur gauche de ce parent). Comme élément inline que le parent ne se soucie pas de la hauteur de son contenu et reste donc à petit, mais comme élément de bloc il s'étend à la taille de son parent et ainsi obtenu à haut, voir violon de démonstration . L'astuce semble être de donner à ce parent une très petite hauteur de ligne (par exemple 0) et de l'afficher comme un bloc en ligne. De cette façon, le parent croîtra selon ses enfants.

testé dans Opera 11, Chrome 11, IE8, IE9, FF4 et Safari 5 avec tous les DTD. IE7 échoue, mais un alignement central de la photo avec un badge à la bonne position n'est pas si mauvais du tout. fonctionne aussi pour IE7 maintenant parce que j'ai supprimé les espaces dans le markup dans le a étiquette. Haha, comme c'est bizarre!

15
répondu NGLN 2011-06-05 19:57:32

EDIT3: cette solution est très similaire à la mienne. Je n'ai pas vraiment regardé ton code, donc j'aurais dû le remarquer plus tôt. Votre étiquette a est déjà enveloppant chaque image donc vous pouvez juste ajouter le badge là-dedans et le positionner absolu. L'étiquette a n'a pas besoin de largeur/hauteur. Vous devez également ajouter l'image du badge au début de votre étiquette a .

Démo: http://jsfiddle.net/wdm954/czxj2/1 /

div.free_tile {
    width: 176px;
    height: 206px;
    float: left;
}

a.img_container {
    display: block;
    margin-bottom: 10px;
}

span.transect_badge {
    display:block;
    position: absolute;
    height: 20px;
    width: 20px;
    background-image: url('/images/transect-badge.png');
}

HTML...

<a class="img_container canonical" href="/photos/10">
    <span class="transect_badge"></span>
    <img class="canonical" src="path/to/img" />
</a>

autres solutions...

dans mon code j'utilise des balises SPAN pour simuler des images, mais c'est la même idée. L'image de l'insigne, lorsqu'elle est positionnée absolute , créera l'effet désiré.

Démo: http://jsfiddle.net/wdm954/62faE /

EDIT: Dans le cas où vous avez besoin de jQuery pour la position. Cela devrait fonctionner (où .la boîte est votre conteneur et .le coin est l'image de l'insigne)...

$('.box').each(function() {
    $(this).find('.corner')
        .css('margin-top', ( $(this).width() - $(this).find('.img').width() ) / 2);
    $(this).find('.corner')
        .css('margin-left', ( $(this).height() - $(this).find('.img').height() ) / 2);
});

EDIT2: une autre solution serait d'envelopper chaque image avec un nouveau conteneur. Vous devrez déplacer le code que vous utilisez pour centrer chaque image dans la classe du nouveau conteneur d'emballage.

Démo: http://jsfiddle.net/wdm954/62faE/1 /

$('.img').wrap('<span class="imgwrap" />');
$('.imgwrap').prepend('<span class="badge" />');

Techniquement, vous pouvez juste ajouter quelque chose comme ceci votre HTML cependant sans utiliser jQuery pour l'insérer.

2
répondu wdm 2011-05-22 17:04:49

utilisez un élément autre que <div> , p.ex. <span> et insérez-le dans votre élément <a> après l'élément <img> . Ensuite, donnez l'élément <a> position:relative; et le <span> obtient position:absolute; top:0px; left:0px; . C'est, si vous n'avez pas l'esprit de l'insigne également partie de la même lien, mais c'est le moyen le plus facile. En outre, la raison d'utiliser <span> est de garder votre HTML4 valide, <div> serait toujours HTML5 valide, cependant.

0
répondu Andy E 2011-05-21 20:39:45

j'ai trouvé une solution en utilisant jQuery. Je ne préfère car cela a un impact notable sur le chargement de la page, mais c'est acceptable si rien d'autre ne fonctionne. Je suis plus intéressé par l'idée de NGLN qui semble prometteuse, mais je n'ai pas encore tout compris. Cependant, comme ce fil a repris beaucoup de trafic, j'ai pensé que je posterais une solution que j'ai trouvé pour les futurs lecteurs à considérer:

compte tenu de cette majoration:

<div class="free_tile">
  <a class="img_container canonical" href="/photos/10">
    <img class="canonical" src="http://s3.amazonaws.com/t4e-development/photos/1/10/andrew_burleson_10_tile.jpg?1303238025" alt="Andrew_burleson_10_tile">
    <span class="transect-badge"></span>
  </a>
  <div class="location">Houston</div>
  <div class="taxonomy"> T6 | Conduit | Infrastructure </div>
</div>

même CSS qu'en question sauf:

span.transect-badge { display: block; height: 20px; width: 20px; position: absolute; background: url('/images/transect-badge.png'); }

alors ce jQuery résout le problème:

$(function() {
  $('img.canonical').load( function() {
    var position = $(this).position();
    $(this).next().css({ 'top': position.top+1, 'left': position.left+1 });
  });
});

comme je l'ai dit, cependant, cela entraîne un temps d'exécution considérable du côté du client, donc je préférerais utiliser une solution non JS si je peux. Je vais continuer à laisser cette question ouverte pendant que je teste et donne des commentaires sur les autres solutions proposées, avec l'espoir de trouver l'une d'entre elles réalisable sans JS.

0
répondu Andrew 2011-05-22 17:57:26