Заметки веб-работника
26 февраля 2007

Таблицы с вертикальным направлением текста

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

Таблица с вертикальным направлением текста

Удивительно, но столь привычное и удобное форматирование нехарактерно для веба из-за отсутствия должной поддержки. С приходом CSS3 такая поддержка появится, но пока, подобные таблицы создаются, как правило, при помощи изображений без использования предназначенных для этих целей табличных тегов. Что ж, будем ждать светлых времен, однако что мешает нам поэкспериментировать и попытаться найти решение уже сейчас?

Задача: Дана таблица

<table class="example">
   <tr>
      <td colspan="3">Сроки наблюдения, сут</td>
      <td>3</td>
      <td>6</td>
      <td>9</td>
      <td>12</td>
   </tr>
   <tr>
      <td rowspan="12" class="vertical">Содержание основных клеточных элементов, %</td>
      <td rowspan="3" class="vertical">Нейтрофилы</td>
      <td>Хлоргексидин</td>
      <td>49.3</td>
      <td>31.5</td>
      <td>23.5</td>
      <td>24.5</td>
   </tr>
   <tr>
      <td>Левосин</td>
      <td>43.4</td>
      <td>25.3</td>
      <td>19.5</td>
      <td>19.4</td>
   </tr>
   <tr>
      <td>Левосин + прополис</td>
      <td>32.5</td>
      <td>22.3</td>
      <td>16.2</td>
      <td>13.4</td>
   </tr>
   <tr>
      <td rowspan="3" class="vertical">Макрофаги</td>
      <td>Хлоргексидин</td>
      <td>1.0</td>
      <td>1.4</td>
      <td>18.9</td>
      <td>29.5</td>
   </tr>
   <tr>
      <td>Левосин</td>
      <td>2.1</td>
      <td>1.3</td>
      <td>17.4</td>
      <td>32.1</td>
   </tr>
   <tr>
      <td>Левосин + прополис</td>
      <td>4.1</td>
      <td>3.8</td>
      <td>27.5</td>
      <td>29.5</td>
   </tr>
   <tr>
      <td rowspan="3" class="vertical">Лимфоциты</td>
      <td>Хлоргексидин</td>
      <td>1.1</td>
      <td>3.5</td>
      <td>1.1</td>
      <td>1.9</td>
   </tr>
   <tr>
      <td>Левосин</td>
      <td>1.9</td>
      <td>2.9</td>
      <td>3.2</td>
      <td>3.8</td>
   </tr>
   <tr>
      <td>Левосин + прополис</td>
      <td>6.6</td>
      <td>2.7</td>
      <td>2.1</td>
      <td>2.7</td>
   </tr>
   <tr>
      <td rowspan="3" class="vertical">Фибробласты</td>
      <td>Хлоргексидин</td>
      <td>1.0</td>
      <td>1.0</td>
      <td>11.5</td>
      <td>28.1</td>
   </tr>
   <tr>
      <td>Левосин</td>
      <td>1.8</td>
      <td>2.3</td>
      <td>15.2</td>
      <td>25.2</td>
   </tr>
   <tr>
      <td>Левосин + прополис</td>
      <td>4.1</td>
      <td>3.9</td>
      <td>23,4</td>
      <td>25.9</td>
   </tr>
</table>
необходимо, чтобы текст в ячейках с классом vertical при отображении в браузере имел вертикальное направление «снизу-вверх».

CSS-решение существует лишь для Internet Explorer. Только этот «неправильный» браузер, начиная с версии 5.5, частично поддерживает предусмотренное в CSS3 для этих целей свойство writing-mode. Содержится у IE на вооружении и пропиетарное layout-flow, однако ни с помощью первого, ни при помощи второго свойства мне так и не удалось задать тексту нужное направление «снизу-вверх». Пришлось дополнительно использовать фильтры flipH и flipV для горизонтального и вертикального поворота текста. Окончательно приходим к следующему описанию класса vertical:

td.vertical{
   writing-mode:tb-rl;
   filter:flipH flipV;
   background:#fff; /* для устранения бага с отображением текста в IE6 и ниже */
   …
}

Задав указанные стили, текст в Internet Explorer отобразится в нужном направлении.

В поисках же универсального решения в первую очередь на ум приходит очевидная идея: заменить текстовое содержимое на идентичное графическое, но повернутое на 90 градусов. Для примера, текст «Hello World!» может быть заменен на что-нибудь вроде <img src="?text=Hello+World%21">, или «Содержимое основных клеточных элементов» – на <img src="?text= %D1%EE%E4%E5%F0%E6%E8%EC%EE%E5+%EE%F1%ED%EE%E2%ED%FB%F5 +%EA%EB%E5%F2%EE%F7%ED%FB%F5+%FD%EB%E5%EC%E5%ED%F2%EE%E2">. Основная нагрузка по генерации такого псевдо-текста в этом случае ляжет на серверную часть, а значит можно говорить о кроссбраузерности.

Этот же подход может быть воплощен и на клиентском уровне. Среди многочисленных методик замены текста изображением, для нашего случая можно применить популярный sIFR – заменить текст флеш-роликом, либо воспользоваться способностью передовых браузеров генерировать SVG-изображения. Последний прием я и решил продемонстрировать в качестве примера решения.

В этом случае, наша задача фактически сводится к созданию SVG-разметки, которой мы заменим текст в нужных нам ячейках. Включить SVG-изображение в HTML-документ можно так:

<object type="image/svg+xml" data="filename.svg" width="100" height="100"></object>
, либо так
<object type="image/svg+xml" data="data:image/svg+xml;<svg xmlns='http://www.w3.org/2000/svg'>…(SVG-разметка)…</svg>" width="100" height="100"></object>
Ниже, пример JavaScript-кода, содержащего подходящую SVG-разметку и выполняеющего необходимую замену (функцию GetVerticalLayout() необходимо привязать к событию onload страницы):

function GetVerticalLayout()
{
   /* Параметры */
   var fontFamily = "Arial"; /* задаем шрифт */
   var fontSize = 12; /* задаем размер шрифта */
      
   var notIE = !(navigator.appVersion.indexOf("MSIE") != -1 && navigator.systemLanguage);
   var supportSVG = document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1");

   if (notIE && supportSVG)
   {
      /* Собираем все ячейки */
      var td = document.getElementsByTagName("td");
      
      /* Находим ячейки с классом vertical и заменяем в них текст svg-изображением */
      var objElement = document.createElement("object");
      
      for(i = 0; i < td.length; i++)
      {
         if (td[i].className.match(/vertical/i))
         {
            var text = td[i].innerHTML;
            var h = td[i].clientHeight;
            var w = td[i].clientWidth;
            
            var obj = objElement.cloneNode(true);
            obj.height = (h > w) ? h : w;
            obj.type = "image/svg+xml";
            obj.width = fontSize + 2;
            obj.data = "data:image/svg+xml;charset/windows-1251,<svg xmlns='http://www.w3.org/2000/svg'><text x='" + (- obj.height/2) + "' y='" + fontSize + "' style='font-family:" + fontFamily + "; font-size:" + fontSize + "px; text-anchor:middle' transform='rotate(-90)'>" + text + "</text></svg>";
            td[i].replaceChild(obj, td[i].firstChild);
         }
      }
   }
}

Если браузер поддерживает SVG, то в соответствующих ячейках текст отобразится должным образом. Так происходило в Opera 9 и в Gecko, начиная с версии 1.8. В Internet Explorer замену не производим, так как для этого веб-проводника существует упомянутое выше простое решение, кроме того, для отображения SVG в IE нужны внешние плагины, которые, скорее всего, не будут установлены у пользователя.

Рабочий пример можно посмотреть здесь.


Теги: JavaScript SVG

Комментарии

1
LonWolfius (Пт, 22 Фев 2008 9:13:18 +0200)
 

ОГРОМНОЕ СПАСИБО!
Ваша статья очень помогла мне.

2
Molodoy (Вт, 22 Июл 2008 17:44:41 +0300)
 

побольше таких оставляй. интересно

3
петр (Чт, 5 Фев 2009 3:32:58 +0200)
 

нефига не работает в мозилке

4
Антон (Ср, 11 Ноя 2009 0:49:53 +0200)
 

Спасибо.
Пример не работает в Хроме :(

5
Believer (Вт, 2 Мар 2010 12:34:00 +0200)
 

Если так сделать, то в мозилке ) зароботает if (notIE/* && supportSVG*/) ..........

6
rivex (Пт, 3 Сен 2010 15:07:38 +0300)
 

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

7
moskittt (Сб, 15 Окт 2011 13:20:05 +0300)
 

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

8
Дмитрий (Сб, 6 Июл 2013 18:56:57 +0300)
 

Не работает не один пример, даже вставил вашу таблицу все горизонтально

9
BMWodin (Ср, 10 Сен 2014 9:05:39 +0300)
 

rivex (Пт, 3 Сен 2010 15:07:38 +0300)

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

Попробуй поставить стиль в этой <td> text-align: left; при повороте должен прижать к низу. А вот как в хроме кодировку кирилицы...вопрос.

_______

Вы можете оставить свой отзыв по данной статье:

  Имя
  E-mail (не публикуется)
  Веб-сайт

Комментарий (Теги форматирования не поддерживаются)