Как обойти просчет ширины в Firefox

0

В некоторых ситуациях Firefox грубо просчитывает ширину некоторых элементов DOM, что, в свою очередь, приводит к разрыву макетов.

Этот пример jsFiddle дает пример проблемы. Цифры, отображаемые под таблицей, - это ширина (в пикселях) div которая затенена темно-серой и ее родителя (как сообщается jQuery). Сравните результаты, полученные в последних версиях Firefox (или IE 11) и Chrome (или Safari). Chrome всегда сообщает 250 обоим ширинам (как и ожидалось), но Firefox всегда сообщает большее количество (хотя точное число может зависеть от ОС и/или версии FF и/или фазы луны). В результате этого недостаточно места для отображения элементов svg в следующем td в 3/ряд.

(Еще более сбивает с толку: цифры, отображаемые под таблицей, будут меняться в зависимости от количества элементов svg включенных во второй элемент td.)

Это неустойчивое/непредсказуемое поведение делает практически невозможным проектирование макета.

Как я могу гарантировать, что FF будет правильно вычислять такие ширины или, альтернативно, как я могу обойти эту ошибку?

EDIT: обновлен jsFiddle (включая ссылку на него).


Теперь, чтобы боги SO были счастливы:

body > div,table,table *{outline:1px solid red;}

html,body{height:100%;}
*{
  -webkit-box-sizing:border-box;
     -moz-box-sizing:border-box;
          box-sizing:border-box;
}
*{margin:0;padding:0;border:0;}
table{
  border-spacing:0;
  border-collapse:collapse;
}

body{
  font-family:courier;
  font-size:13px;
  background-color:palegoldenrod;
}

body > div{
  width:312px;
  margin:0 auto;
  padding:40px 0 0;
  background-color:white;
  min-height:100%;
}

label{
  display:block;
  padding:0 1ex;
}

.button-container{
  color:white;
  background-color:#555;
}
.button-container > div{
  display:inline-block;
}

.button-container > div:first-child{
  font-weight:bold;
}

.ul-container > div{
  width:100%;
  border:1px solid black;
  -webkit-border-radius:4px;
          border-radius:4px;
}
ul{list-style:none;}
li{
  width: 72px;
  float:left;
  margin: 0px 5px 1px;
  padding: 0px 5px;
  border-width: 1px;
  line-height: 14px;
}
br{
  clear:left;
}

body > div > div:last-child{margin:40px;}


<body>

  <div>

    <table><tbody><tr>
      <td>

         <div class="button-container">
           <div>xxxx xxxxx</div>
           <div>
             <label> <input type="radio"> xxxx xxxx xxx xxxx xxxx </label>
           </div>
         </div>

         <div class="ul-container" style="width: 250px;">
           <div style="width: 248px;">
             <ul style="width: 246px;">
               <li>A</li><li>B</li><li>C</li><li>D</li><li>E</li><li>F</li><li>G</li><li>H</li><li>I</li>
             </ul>
             <br>
           </div>
         </div>

      </td>

      <td>
        <div>
          <svg width="20" height="20"></svg><svg width="20" height="20"></svg><svg width="20" height="20"></svg><svg width="20" height="20"></svg><svg width="20" height="20"></svg><svg width="20" height="20"></svg><svg width="20" height="20"></svg>
        </div>
      </td>

    </tr></tbody></table>

    <div></div>

  </div>


(function ($) {
  var $msg = $('body > div > div:last-child');
  function showw (sel) {
    var w = $(sel).width();
    $('<span>', {text: '' + w})
        .css('margin-left', 5)
        .appendTo($msg);
    console.log(w);
  }
  showw('.button-container');
  showw('table td:first-child');
}(jQuery));
Теги:
svg
firefox

2 ответа

1
Лучший ответ

Если вы удалите правило inline-block для .button-container > div, он заставляет два divs сидеть на отдельных строках, позволяя таблице принимать согласованную ширину.

Что происходит, браузер пытается поместить элементы в одну строку. Ячейка в таблице без инструкций ширины или переполнения будет расширяться, чтобы разместить внутри нее строки содержимого. Поскольку два элемента являются встроенными, они считаются одной строкой. Текст обертывается, как и следовало ожидать (браузер выполняет хорошую работу, защищая целостность вашего содержимого), но это произвольно, поскольку вычисляется ширина; он влияет на вычисленную ширину линии, которую формируют элементы, и, следовательно, толчок к расширению ячейки таблицы. Браузер пытается взять то, что вы ему дали, и понять его, в то время как он также пытается сохранить целостность и разборчивость ваших данных, потому что это таблица и какие таблицы делают.

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

Скрипт: http://jsfiddle.net/Cy7dA/

  • 0
    Я думаю, это вопрос мнения: ошибка одного человека - это особенность другого человека. То, как Chrome и Safari справляются с этим вопросом, мне кажется правильным, но разумные умы могут не согласиться с этим. Кстати, я подправил пример того, что для Chrome и Firefox требуется две строки для отображения содержимого .button-container , но исходная ситуация была такова, что в Windows требовалась только одна строка, а в OS X - две строки , Расположение в одну строку, когда это было возможно, было предпочтительным, и это было причиной для inline-block . Без этого две линии будут применены, будь то ...
  • 0
    ... требуется или нет.
Показать ещё 3 комментария
1

Это вовсе не "просчет ширины".

Ваша проблема заключается в том, что ваш ярлык и ввод различаются по ширине в обоих браузерах. Дополнительная ширина затем нажимает кнопку-контейнер и td.

Постарайтесь, чтобы ваша комбинация ввода/метки была совместима между браузерами (вам, вероятно, нужны явные поля на входе), и ваша проблема решена.

  • 0
    посмотрите на текст: его правый край находится далеко от правого края содержащего элемента; ширина текста составляет 205 пикселей, намного ниже ширины, которую FF назначает содержащему элементу.
  • 0
    Да, но удалите метку / ввод и посмотрите, что произойдет. У вас есть куча странных глобальных селекторов, поэтому есть большая вероятность, что вы получите большой правый запас после лейбла.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню