Подтвердить что ты не робот

Позиционировать значок над углом изображения автоматически

У меня есть макет, где изображения "плавают" в определенной области. Макет выглядит следующим образом:

Layout Example

Источник, подобный этому:

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

- EDIT-- Здесь проблема: изображение плавает внутри контейнера, поэтому угол изображения может падать где-то внутри внешних границ контейнера. Вот пример того, что произойдет, если я попытаюсь использовать position:absolute; top:0; left:0 внутри одного и того же контейнера, изображение связано: The problem

4b9b3361

Ответ 1

Произошло несколько попыток, но вот это: независимый от размера значок позиционирования значка.

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

Пример:

В предыдущих менее успешных попытках (см. историю изменений) проблема заключалась в том, что изображение было вертикально центрировано, чтобы получить его родитель того же размера (чтобы расположить значок в левом верхнем углу этого родителя). В качестве встроенного элемента родительский элемент не заботится о высоте его содержимого и, следовательно, остается небольшим, но как элемент блока он растягивается до размера родителя и, таким образом, достигает максимума, см. демонстрационная скрипка. Кажется, что трюк должен дать этому родителю очень маленькую высоту строки (например, 0) и отобразить ее как встроенный блок. Таким образом, родитель будет расти в соответствии с его дочерними элементами.

Протестировано в Opera 11, Chrome 11, IE8, IE9, FF4 и Safari 5 со всеми DTD. IE7 завершается с ошибкой, но выравнивание по центру с фотографией с значком в правой позиции не так уж плохо. Работает также для IE7 сейчас, потому что я удалил пробелы в разметке в a. Ха-ха, как странно!

Ответ 2

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/

EDIT: в случае, если вам нужно 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 для его вставки.

Ответ 3

Используйте элемент, отличный от <div>, например. <span> и поместите его в элемент <a> после элемента <img>. Затем введите <a> элемент position:relative;, а <span> получит position:absolute; top:0px; left:0px;. То есть, если вы не возражаете, чтобы значок также был частью одной и той же ссылки, но это самый простой способ. Кроме того, причина использования <span> заключается в том, чтобы ваш HTML4 был действительным, однако <div> все равно был бы HTML5.

Ответ 4

Я нашел одно решение с помощью 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.