【问题标题】:Position badge over corner of image automatically自动将徽章放置在图像的一角
【发布时间】:2011-08-30 08:52:43
【问题描述】:

我有一个布局,其中图像“浮动”在某个区域内。布局如下所示:

来源如下:

<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>

CSS 看起来像这样(在 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'); }

因此,基本上图像位于垂直对齐的中间和文本对齐的中心,它们的最大宽度为 176,最大高度为 158,但它们被裁剪以保持原始纵横比,因此实际的顶角每张图片的落差会有所不同,具体取决于它是哪张图片。

我有一个徽章,我想把它放在某些图片的顶角(当图片是“规范”时)。您会看到上面的样式 (div.transect_badge)。

当然,问题是我不知道图像的上角在哪里,所以我无法通过 CSS 硬编码位置。

我假设我需要通过 jQuery 或其他方式来执行此操作。因此,我开始使用 jQuery 方法来自动将徽章 div 附加到任何规范图像。这很好用,但我不知道如何将它放在左上角。

如何做到这一点? (理想情况下只使用 HTML 和 CSS,但实际上使用 JS/jQuery)

--编辑-- 问题是:图像漂浮在容器内,因此图像的角可能落在容器外部范围内的任何位置。下面是一个例子,如果我尝试在图像绑定的同一个容器内使用 position:absolute; top:0; left:0 会发生什么:

【问题讨论】:

  • 如果您使用relativeabsolute 定位,CSS 知道左上角。虽然您仍然需要使用 jQuery 插入徽章标记。
  • Jason - 由于图像标签不能包含其他元素,因此绝对位置对我有什么帮助?图像所在的锚标记比图像大——所以当我用 CSS 定位绝对位置时,我得到的标记位于外部边界框的左上角,而不是图像。
  • 锚点内的 badge 元素是可以接受的。但是,如果您的风格无法做到这一点,那就不用担心了。这就是为什么我没有回答,只是确保您考虑了 CSS 定位。我就是这样做的。

标签: javascript jquery html css position


【解决方案1】:

试了一下,这里是:the size independent image badge positioner

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;
}

例子:

在以前不太成功的尝试中(请参阅编辑历史记录),问题在于使图像垂直居中并使其父级大小相同(以便将徽章定位在该父级的左上角)。作为内联元素,父元素不关心其内容的高度,因此保持较小,但作为块元素,它会拉伸到父元素的大小并因此变高,请参阅demonstration fiddle。诀窍似乎是给该父级一个非常小的行高(例如 0)并将其显示为内联块。这样,父母将根据其孩子成长。

在包含所有 DTD 的 Opera 11、Chrome 11、IE8、IE9、FF4 和 Safari 5 中测试。 IE7 失败,但在正确位置将带有徽章的照片居中对齐并没有那么糟糕。 现在也适用于 IE7,因为我删除了 @987654326 中标记中的空格@ 标签。哈哈,好诡异!

【讨论】:

  • 好吧,这看起来很有希望——不过我有点困惑,虚拟图像到底有什么用途?
  • 嗯,嗯…… ;) 实际上,您可以消除虚拟图像,然后还可以消除 photo 样式。然后它与 Andy E 提供的解决方案相同。顺便说一句,刚刚更新了 Opera,小提琴就不能像以前那样工作了。奇怪。
  • @Andrew:抱歉花了这么长时间。我决心解决这个问题,但忘记了。幸运的是,我已将其添加到我的收藏夹中。成功。
  • 嘿 NGLN -- 很抱歉我花了这么长时间才回到我的应用程序的这一部分并测试你的代码,但我终于做到了,我发现你的解决方案在不使用 jQuery 的情况下也能完美运行。不再有闪烁的徽章被脚本弹出,耶!
【解决方案2】:

我确实找到了一种使用 jQuery 的解决方案。我不喜欢这个,因为它显着影响页面加载,但如果没有其他方法也可以接受。我对 NGLN 的想法更感兴趣,这似乎很有希望,但我还没有完全弄清楚。然而,由于这个帖子吸引了很多流量,我想我会发布一个我想出的解决方案供未来的读者考虑:

鉴于此标记:

<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>

与所讨论的 CSS 相同,除了:

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

那么这个jQuery就解决了问题:

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

不过,就像我说的那样,这会在客户端产生明显的运行时间,所以如果可以的话,我更愿意使用非 JS 解决方案。在我测试并就提供的其他解决方案提供反馈时,我将继续保留这个问题,希望找到其中一个在没有 JS 的情况下也可以使用。

【讨论】:

    【解决方案3】:

    EDIT3:这个解决方案与我原来的解决方案非常相似。我并没有真正看你的代码,所以我应该早点注意到这一点。您的a 标签已经包裹了每张图片,因此您只需在其中添加徽章并将其绝对定位即可。 a 标签不需要宽度/高度。此外,您必须在 a 标签的开头添加徽章图片。

    演示: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>
    

    其他解决方案...

    在我的代码中,我使用 SPAN 标签来模拟图像,但这是相同的想法。徽章图像在定位到absolute 时,将创建所需的效果。

    演示:http://jsfiddle.net/wdm954/62faE/

    编辑:如果您需要 jQuery 来定位。这应该可以(其中 .box 是您的容器,.corner 是徽章图像)...

    $('.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:另一种解决方案是用新容器包装每个图像。您必须将用于将每个图像居中的代码移动到新包装容器的类中。

    演示:http://jsfiddle.net/wdm954/62faE/1/

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

    从技术上讲,您可以在 HTML 中添加类似这样的内容,但无需使用 jQuery 插入。

    【讨论】:

    • wdm,感谢您的建议,但是如果图像不是恒定的宽度和高度,这将不起作用。在我的情况下,每个图像的高度和宽度都是可变的,最大宽度为 176 像素,高度为 158 像素。无论图像的纵横比如何,都将决定渲染缩略图的特定高度和宽度。为了创建一致的网格效果,img 在一个高度为 158、宽度为 176 的块元素(锚标记显示块)内是文本对齐中心和垂直对齐中间...
    • ... 容器元素内的任何绝对定位都将相对于作为外部边界框的容器元素进行定位,而不是图像本身。因此,正如您在我发布的照片​​中看到的那样,这会导致徽章无法正确排列在图像上。
    • 请查看编辑。我添加了一些 jQuery,它将找到居中位置图像的角应该在哪里。
    • 我上次的编辑应该会更好。为每个图像添加一个包装将允许徽章位于角落,因为包装将与图像的大小相同。不需要动态定位。
    • 刚刚添加了 EDIT3...这些应该足以让这件事发挥作用。
    【解决方案4】:

    使用&lt;div&gt; 以外的元素,例如&lt;span&gt; 并将其放在 &lt;a&gt; 元素中 &lt;img&gt; 元素之后。然后,给&lt;a&gt; 元素position:relative;&lt;span&gt; 得到position:absolute; top:0px; left:0px;。也就是说,如果您不介意徽章也属于同一链接的一部分 - 但这是最​​简单的方法。此外,使用&lt;span&gt; 的原因是为了保持您的HTML4 有效,但是&lt;div&gt; 仍然是HTML5 有效的。

    【讨论】:

    • @Andrew:从a.img_container 规则中删除height/width 维度。保持&lt;img&gt; 元素的高度/宽度,并使&lt;a&gt; 元素与内容大小相同。
    • 整个问题是每个图像的高度和宽度都是可变的。所以它们在外部边界框(我写的锚标记)内垂直和水平居中,但是每个图像在边界框内的确切大小是不同的。
    • @Andrew:我现在明白了。在这种情况下,最好的方法是在&lt;a&gt; 元素内创建一个&lt;span&gt; 元素,并将&lt;img&gt; 和徽章移动到该元素中。这样,徽章将绝对定位到 &lt;span&gt; 父级,它只会与 &lt;img&gt; 一样大
    • 试过了,似乎水平工作但不是垂直工作。如果你确定这可以工作,你可以发布一个演示吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-06
    • 2020-10-11
    • 2018-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    相关资源
    最近更新 更多