2014-09-27 3 views
2

Некоторое время я был в тупике, мои центрированные фоновые изображения не были выровнены по пикселям в их контейнерах. У меня даже были разные результаты в одном браузере, но в разных окнахCSS-центрирование изображений в центрированном контейнере дает непредсказуемые результаты

Наконец-то я узнал, что происходит, но у меня все еще не хватает надежного кросс-браузерного решения.

Корпус: Я работаю над сворачиваемым древовидным представлением в javascript. Все работает нормально, но в некоторых случаях кнопки свернуть/развернуть с одного пикселя влево.

Изображения для этих кнопок определяются пользователем, а также размер (ширина) контейнера, в котором они находятся. Изображения рисуются в центре этих контейнеров с помощью background-position: center center;. Теперь есть случаи, когда изображение не может быть установлено точно в центре контейнера (например, центрируя изображение 9px в контейнере 20px, с каждой стороны есть разница в 1 пиксель). Это не должно быть проблемой, если у нас есть последовательное поведение в отношении того, как браузер справляется с этим.

Но вот где это становится грязным: я реализовал этот древовидный вид внутри обертки с центром margin:0 auto; на основе окна просмотра браузеров. И вот когда я получаю разные результаты, когда центрирование и фокусное центрирование не подходят точно в пределах границ пикселей.

Это, вероятно, трудно следовать, поэтому я нажал на проблему в скрипкой: http://jsfiddle.net/3y65wgu8/1/

CSS:

#wrapper1 { 
    width:400px; 
} 
#inner1 { /* perfect center */ 
    margin:0 auto; 
    width:200px; 
    height:50px; 
} 
#wrapper2 { 
    width:399px; 
} 
#inner2 { /* 1px-offcenter */ 
    margin:0 auto; 
    width:200px; 
    height:50px; 
} 
#container { /* image 1px-offcenter (9px centered in 12px container) */ 
    width:12px; 
    height:12px; 
    background:url(data:image/gif;base64,R0lGODlhCQAJALMAANLNve/s58a7rd7Vznuatf////f39wAAALXD1vfz7+fj3tbTxsa6pdbPxt7b0sa2pSH5BAAAAAAALAAAAAAJAAkAAAQoEJFJiSw4l6mxmUYYJgp4nKczJUngKsOkOMOyNMAECALDPAJLhYKIAAA7) no-repeat center center #444; 
} 

HTML:

<div id="wrapper1"> 
    <div id="inner1"> 
     <div id="container"></div> 
    </div> 
</div> 
<div id="wrapper2"> 
    <div id="inner2"> 
     <div id="container"></div> 
    </div> 
</div> 

Два разных оберток центрирования их содержащего два идентичных контейнера, имеющих небольшую кнопку, выполненную в виде фона. Chrome, похоже, единственный браузер, который последовательно выравнивает кнопки выравнивания, но firefox и IE показывают проблему, которую я описал. Попробуйте изменить размер окна браузера и увидите, как кнопки отскакивают с одной стороны на другую.

Мой вопрос: как я могу получить хотя бы идентичные результаты, не теряя при этом гибкость при калибровке и стилизации кнопок/контейнера/обертки.

EDIT: Вот картина, которая иллюстрирует мою потребительной случай:

Example

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

+0

Является ли контейнер для изображения фиксированным? Если это так, то если вы храните метаданные для изображения в базе данных (например, местоположение, подпись), возможно, вы также можете сохранить размеры изображения. Учитывая размеры изображения, вы можете рассчитать, на стороне сервера (Math.Floor), целочисленное значение для желаемого смещения для фонового положения для каждого изображения, а затем вы не будете во власти нежелательного округления браузера. –

+0

@AndrewMorton нет, это не так, внешний вид древовидной структуры в значительной степени настраиваемый и может быть практически любого размера. Однако этот контейнер всегда квадратный. Размер изображения также является переменной. Извлечение метаданных изображения и их использование должны работать в большинстве случаев, но я считаю, что должно быть более простое решение :) – Pantalaimon

+0

При добавлении JsFiddle приятно, пожалуйста, также разместите соответствующий раздел кода в вопросе. JsFiddle может перестать работать в один прекрасный день, и вопрос должен оставаться понятным без внешних ресурсов. – k0pernikus

ответ

1

Там, кажется, нет никакого способа обойти это, чем изменить размер контейнера изображения, когда изображение внутри не может быть центрированы пиксель совершенны, чтобы иметь согласованное поведение кросс-браузер на позиционировании. Поэтому мне нужно получить метаданные изображения как на стороне сервера, так и на стороне клиента.

стороне сервера (1): Использование getimagesize и getimagesizefromstring и было очевидно, что путь. Но затем я столкнулся с проблемой в моем текущем прецеденте: дерево визуализируется с использованием AJAX, а относительный URL-адрес для изображения не относится к расположению сценария AJAX.

Вопросы: Таким образом, для этой работы я либо должен пройти как URL и абсолютный путь (или только абсолютный путь, и есть URL выяснял отгонкой $_SERVER['DOCUMENT_ROOT'] от него). Этот подход кажется противоречивым и ограничивающим частью разработчика, пытающейся реализовать этот древовидный модуль. Поэтому я отказался от этой идеи.

Серверная сторона (2): Задайте размеры изображения во время разработки. Просто и просто, возложите ответственность на исполнителя.

Вопросы: Не очень элегантный, но он работает :). (раствор 1)

сторона клиента: я, но оба изображения внутри скрытого DIV, и я принести размер изображения с события загрузки. Если по этим данным изображения, используемые внутри контейнеров, отображаются не по центру (image.width%2 != container.width%2, image.height%2 != container.height%2), я просматриваю эти контейнеры и изменяю их размер на один пиксель шириной или высотой.

Вопросы: Мне не нравится идея использования скрытых элементов с триггерами с единственной целью решения этой проблемы позиционирования. Однако он обеспечивает надежное кросс-браузерное решение. Единственным недостатком является то, что, кажется, небольшая задержка до того, как изображение «защелкнутся» (по крайней мере, в FireFox). Очевидным решением для этого является наличие в контейнерах изображений после изменение размера контейнера.(solution 2)

+0

Спасибо за публикацию решения этой сложной проблемы :) Я попробовал несколько других методов центрирования CSS, используя display: table, display: inline-block, float и absolute positioning, а дрифт 1px все еще был там, или он был обработан в IE9 или под. – Talkingrock

0

Это, возможно, стоит поспешить. При проверке скрипта я заметил, что # wrapper1 имеет ширину 400 пикселей, а # wrapper2 имеет ширину 399 пикселей. Я изменил ширину # wrapper2 на 400px для согласованности.

Я добавил размер фона: обложка; на кнопку, потому что изображение кнопки выглядит разным размером, чем его контейнер. Попробуйте и посмотрите, что вы думаете.

Если вам нужно сохранить # wrapper2 на 399px, измените положение фона в коде ниже на background-position: вверху слева; при использовании фонового размера: обложка ;.

Другим вариантом для вашего текущего кода было бы сделать фоновое изображение тем же размером, что и его контейнер 12px на 12px, использовать background-position: top left ;, и удалить цвет фона. При создании фоновых кнопок полезно, если фон имеет тот же размер, что и его контейнер.

Примечание. Вы также можете использовать стили CSS, чтобы создать вид кнопки на div, а не использовать изображение.


#wrapper1 {width:400px;} 
#wrapper2 {width:400px;} 
#container { 
width:12px; 
height:12px; 
background-repeat:no-repeat; 
background-position:center center; 
background-size:cover; 
-webkit-background-size:cover; 
-moz-background-size:cover; 
-o-background-size:cover; 
background-image:url(data:image/gif;base64,R0lGODlhCQAJALMAANLNve/s58a7rd7Vznuatf////f39wAAALXD1vfz7+fj3tbTxsa6pdbPxt7b0sa2pSH5BAAAAAAALAAAAAAJAAkAAAQoEJFJiSw4l6mxmUYYJgp4nKczJUngKsOkOMOyNMAECALDPAJLhYKIAAA7); 
} 
+0

Я использовал 400px div и 399px div как пример поведения идеального центра и 1px-offcenter, чтобы показать оба сценария одновременно. Для примера 400px/399px вы должны рассмотреть это окно своего браузера, которое может быть, конечно, любого размера. 'cover' также неприемлемо, так как он растягивает изображение, чтобы заполнить весь контейнер, где я просто хочу, чтобы изображение появилось посередине в исходном размере. Это изображение предоставляется пользователю. Я уточню свой вопрос, чтобы уточнить. – Pantalaimon

+0

Спасибо за разъяснение. Я попробовал несколько других методов, включая термоусадочную упаковку div и размер с дополнением, и дрейф все еще возникал, когда пиксельное изображение с нечетным размером (9 пикселей) находится в контейнере с четным размером (12 пикселей). Есть ли способ сделать контейнер нечетным или даже размерным, чтобы соответствовать изображению (например: 9px-9px изображение в контейнере 13px-13px)? Другой вариант, когда у вас может быть больше элементов управления стилем, - это вставить физический образ с помощью CSS #container: before {content: url (data: image/gif; ...); Это интересный вопрос, поэтому, пожалуйста, напишите, если вы найдете свое собственное решение. – Talkingrock