Отключаем нежелательные HTML-элементы с помощью CSS

    Часто, когда мы сдаем проект клиенту, мы теряем контроль над HTML-кодом. Иногда клиент использует CMS (Системы Управления Контентом), которые дают ему полный контроль над теми или иными частями HTML-кода. Иногда клиент просто использует наши темплейты для вывода своего кода в документ.
    В большинстве случаев довольно тяжело проинформировать клиента о том, как использовать темплейты или CMS, которые вы ему предоставляете, а иногда просто неприемлемо толкать пламенные речи о семантической верстке и веб-стандартах. Клиент может/будет использовать «старую, добрую разметку», ту, которую он знает, просто потому что она работает и выглядит так как он привык. Скорее всего в ней будут присутствовать нежелательные (deprecated) тэги и атрибуты, такие как bgcolor, align и «вечный» font. Эта статья о том, как блокировать нежелательные HTML-тэги с помощью CSS, тем самым аккуратно направляя клиента в правильном направлении.

    Есть несколько решений проблемы. Одно из них — вывод предупреждающего изображения с помощью CSS, когда изпользуются нежелательные тэги. Подробные обьяснения этого способа есть здесь и здесь. Второе решение — «вырезание» нежелательных тегов и атрибутов на стороне сервера. Этот способ является наиболее эффективным, другое дело что не всегда есть контроль за сервером где расположен сайт.
    Идея состоит в том, чтобы сохранить естественный каскад и наследие стилей во всех браузерах, элегантно «отключая» HTML, нежелательный к использованию клиентом. И тогда клиент перестанет использовать его, потому что нежелательные тэги просто перестанут «работать». Элегантный и ненапрягающий клиента способ, который направит его по верному пути.
    Нежелательные HTML-тэги и атрибуты:
    <font>
    <basefont>
    <center>
    <strike>
    <s>
    <u>
    bgcolor
    border
    align
    vspace
    hspace
    valign
    width
    height
    

    Решение
    В идеале мы могли бы просто откорректировать некоторые HTML-тэги, вставив значение inherit для эквивалентного CSS-свойства. Браузеры, работающие по стандартам, просто проигнорируют заданные в коде нежелательные атрибуты и будут использовать вместо них наследуемые значения в каскаде.
    На пример этот CSS:
     font { color:inherit; } 

    будет превалировать над этим кодом:
     <font color="blue">Синий</font>

    Соответственно цвет текста внутри тэга font будет цветом, наследуемым по каскаду, а не синим, как задано в коде. То что надо. Но как вы наверняка знаете — у Internet Explorer есть проблемы с наследуемыми значениями. И в седьмой версии тоже. Так что за работу:
    Expressions и currentStyle в помощь:
    font {
    color:inherit; /* Нормальные браузеры */
    color:expression(this.parentNode.currentStyle['color']); /* IE */ }

    Работает? Отлично, поехали дальше:
    font {
    font-family:inherit; /* Нормальные браузеры */
    font-family:expression(this.parentNode.currentStyle['fontFamily']); /* IE */
    }

    Все чудесно, кроме того что Opera 9 не наследует значение для font-family. К счастью font нас тоже устроит:
    font {
    font:inherit; /* Нормальные браузеры */
    font-family:expression(this.parentNode.currentStyle['fontFamily']); /* IE */
    }

    С этим разобрались. Перейдем к свойству font-size. Здесь нужна деликатность, так как значение размера шрифта наследуется по отношению к вычисляемому (computed) значению. Предыдушие expression'ы здесь не сработают, так как если для body выставлено значение свойства font-size, равное 2em, то вычисление значения размера шрифта начнется от этой точки. Браузер проверит значение font-size для родительского элемента тэга font, которое равняется 2em и представит вычисляемое значение, равное 4em (2em от 2em). А это не то что нам нужно. Решение простое. Нужно использовать начальное значение font-size, равное 100% для всех браузеров. Давайте добавим несколько свойств нежелательному тэгу basefont, чтобы и его утихомирить. Вот полный список правил для «укрощения» тэгов font и basefont:
    font,basefont {
    color:inherit; /* Нормальные браузеры */
    color:expression(this.parentNode.currentStyle['color']); /* IE */
    font:inherit; /* Нормальные браузеры. Font вместо font-size для Оперы */
    font-family:expression(this.parentNode.currentStyle['fontFamily']); /* IE */
    font-size:100%; /* Все браузеры. Размеры наследуются */
    }

    Двигаемся дальше. Давайте воспользуемся базовой техникой, чтобы отменить тэги center, s, strike и u:
    center {
    text-align:inherit; /* Нормальные браузеры */
    text-align:expression(this.parentNode.currentStyle['textAlign']); /* IE */
    }
    s,strike,u {
    text-decoration:inherit; /* Нормальные браузеры */
    text-decoration:expression(this.parentNode.currentStyle['textDecoration']); /* IE */
    }

    Свершилось! Мы «отключили» большинство нежелательных тэгов, используя только CSS и expression'ы.
    А как же атрибуты? HTML4 включает в себя некоторое количество нежелательных атрибутов, которые могут изрядно попортить нервы. Давайте их тоже «повыключаем». Начнем с align:
    *[align] { text-align:inherit; } /* Нормальные браузеры */

    Все бы хорошо, но IE6 не поддерживает селекторы атрибутов. Посему, нам надо модифицировать expression, для того чтобы он проверял наличие атрибута align у тэга. Вот что получилось:
    *[align] { text-align:inherit; } /* Нормальные браузеры */
    * { text-align:expression(this.align ? this.parentNode.currentStyle['textAlign'] : ''); } /* IE */

    Далее на очереди атрибуты тэга img. Помимо атрибута align, мы хотим отключить атрибуты border, vspace и hspace. Так как значения margin и border не наследуются, то здесь применимо простое правило:
    img { margin:0; border:none; } /* Все браузеры */

    Вот здесь мы как раз сталкиваемся с неразрешимой проблемой для IE6. vspace и hspace не равнозначны свойству margin в нем, поэтому IE6 будет продолжать отображать их. Единственное решение, которое пришло мне в голову это написать маленький скриптик, который будет просто удалять эти атрибуты при загрузке документа:
    window.onload = function() {
    for (i=0;i
    document.getElementsByTagName('img')[i].removeAttribute('vspace');
    document.getElementsByTagName('img')[i].removeAttribute('hspace');
    }
    }

    Я бы предпочел не использовать javascript, но в данном случае я просто не вижу другой альтернативы. Так что пусть будет. Теперь добьем атрибут type в тэге ol:
    ol { list-style-type:decimal; } /* Все браузеры */

    А теперь атрибут bgcolor для body:
    body { background-color:transparent; } /* Все браузеры */

    Таблицы. Финальный шаг. В таблицах, в HTML4/4.01, есть ряд нежелательных атрибутов, которые активно использовались для верстки страниц. Но мы же не хотим, чтобы клиент использовал таблицы для верстки? Поэтому давайте отключим атрибуты width, height, bgcolor, valign и border:
    table,tr,th,td {
    width:auto; /* Все браузеры */
    height:auto; /* Все браузеры */
    background-color:transparent; /* Все браузеры */
    vertical-align:inherit; /* Все браузеры (включая IE) */
    border:none; /* Все браузеры */
    }

    Подведем итоги:
    Используя CSS-правила и минимальный javascript, нам удалось «отключить» большинство нежелательных тэгов и атрибутов, элегантно сохраняя естественное наследование. Нам не нужно «учить» клиента, он в любом случае должен будет использовать правильную разметку. С учетом одной, очень важной ремарки — очень важно предоставить клиенту достаточное количество описаных CSS-классов, чтобы он не был ограничен в работе с разметкой.
    Все стили вместе:
    font,basefont {
    color:inherit; /* Нормальные браузеры */
    color:expression(this.parentNode.currentStyle['color']); /* IE */
    font:inherit; /* Нормальные браузеры. Font вместо font-size для Оперы */
    font-family:expression(this.parentNode.currentStyle['fontFamily']); /* IE */
    font-size:100%; /* Все браузеры */
    }
    center {
    text-align:inherit; /* Нормальные браузеры */
    text-align:expression(this.parentNode.currentStyle['textAlign']); /* IE */
    }
    s,strike,u {
    text-decoration:inherit; /* Нормальные браузеры */
    text-decoration:expression(this.parentNode.currentStyle['textDecoration']); /* IE */
    }
    *[align] { text-align:inherit; }  /* Нормальные браузеры */
    * { text-align:expression(this.align ? this.parentNode.currentStyle['textAlign'] : ''); }  /* IE */
    img { margin:0; border:none; }  /* Все браузеры */
    ol { list-style-type:decimal; }  /* Все браузеры */
    body { background-color:transparent; /* Все браузеры */ }
    table,tr,th,td {
    width:auto; /* Все браузеры */
    height:auto; /* Все браузеры */
    background-color:transparent; /* Все браузеры */
    vertical-align:inherit; /* Все браузеры (включая IE) */
    border:none; /* Все браузеры */
    }


    Вольный перевод и подготовка статьи по материалам monc.se
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 38

      0
      Шикарная статья!!!

      Можно так же немного побаловаться и с php, то есть если клиент вводит в визуальный редактор движка ненужные теги, то при выводе контента эти теги просто режутся.

      Буду использовать!!!

      З.Ы.: Где-то видел в сети CSS-фреймворк на подобную тему. Нужно бы найти и выложить на Хабре.
        +2
        Описание некоторых CSS Frameworks и CSS Reset http://www.smashingmagazine.com/2007/09/…
        Сам нераз использовал Tripoli http://monc.se/tripoli/ ... для кроссбраузерности очень хорошая вещь
          0
          Да, да. Это точно!!!
            0
            А на русском есть описание этих "штук"?
          +6
          - Ало, здравствуйте! А вот не работает! А в дизайне от другого дизайнера работало!
            +1
            Приблизительно так и будет. И убеждать клиента, что не надо так делать, как делает он почти бессмысленно. За редким исключением. Для себя я нашел выход. В своей CMS я просто не даю заказчику лишних инструментов для коверкания сайта. Только самый необходимый минимум + выбор предустановленных стилей для блоков текста.
              0
              Через какой-то промежуток времени, давая клиенту достаточно свободы в работе с CMS, я убедился в том, что описаный вами подход единственно правлиьный для не искушённого в IT клиента.
              0
              Да, такое случится скорее всего, но лучше так, чем не делать ничего.
              +2
              Мне кажется, что лучше приложить усилия и надавить на тех, кто может сделать чистку кода на сервере.
                0
                Ага.
                Легче и правильнее всё, задаваемое в визуальных редакторах при сохранении менять по определенным правилам, визуальные теги менять на семантические, фонты на дивы с инлайн стилями (хотя бы так) и всё прочее в том же духе.
                Ну и сам визуальный редактор хорошо бы подкорректировать, если там неправильные теги присутствуют.
                CSS для этого, действительно, не катит.
                  0
                  К сожалению это не всегда возможно и не всегда оптимально.
                  0
                  CSS чтобы скрыть то, что можно еще на сервере вырезать.
                  А в чем плюсы вообще?
                    0
                    У вас всегда есть доступ к серверу клиента?
                      +1
                      Если у клиента есть проблема и он ее хочет решить, он нанял вас (нас), почему бы не потребовать у него еще и доступ? Зачем чинить зуб работая из анального отверстия?
                        0
                        Давайте исходить из того, что это не догма, а лишь один из возможных способов решения проблемы. И в некоторых случаях он имеет право на существование. Вобще часто при работе с клиентами важна гибкость и иногда проще сделать так, чем не бить себя пяткой в грудь, требуя доступ.
                    0
                    клиенту не позавидую :-|
                    по-моему предупреждения во всех отношениях лучше — и цель достигнута, и понятно будет «откуда ноги» растут у отказа привычного кода работать
                      +1
                      Мне кажется, что лучше удалаять ненужные теги прямо в редакторе - тогда сразу видно, как меняется текст. Я сделал просто - высякие теги типа FONT и SPAN вырезаю. А чтобы можно было оставлять форматирование - разрешаю классы внутри разрешенных тегов. Как отличить разрешенный класс от ненужного? Все свои классы для сайта начинаю с префикса, например, r4_div - и проверяю - можно ли этот класс оставить.

                      Может, кому и пригодится. Вот некоторые куски кода:

                      var allowTags=Array('P','B','I','UL','LI','OL','DIV','H1','H2','H3','TABLE','TBODY','TR','TD','A','CENTER','INPUT','TEXTAREA','FORM','IMG','OBJECT','EMBED','PARAM');
                      var clearTags=Array('SPAN','O:P','FONT','COL','COLGROUP','U','O','font','small');
                      var allowClaPrefix='r4_';

                      function ieClearStyles(coll,count)
                      {

                      if(count>860)
                      return;
                      var coll=coll.children;

                      if (coll!=null)
                      {
                      for (var i=0; i coll.length; i++)
                      {
                      //alert("Tag: "+coll[i].tagName+", Count: "+count);
                      var claName=coll[i].className;
                      if(allowClaPrefix==claName.substring(0,3))
                      {
                      coll[i].style.cssText="";
                      }
                      else if(coll[i].tagName=='OBJECT' || coll[i].tagName=='EMBED' || coll[i].tagName=='PARAM')
                      {
                      // do nothing width video
                      }

                      else
                      {
                      if(coll[i].tagName=='A')
                      {
                      coll[i].style.cssText="";
                      coll[i].className='';
                      }
                      else if(coll[i].tagName=='TD' || coll[i].tagName=='TH')
                      {
                      coll[i].style.cssText="";
                      if(coll[i].className && allowClaPrefix!=claName.substring(0,3))
                      coll[i].className="";
                      else
                      var cla=coll[i].className;

                      var rows=coll[i].getAttribute('rowspan');
                      var cols=coll[i].getAttribute('colspan');
                      coll[i].clearAttributes();
                      coll[i].setAttribute('colspan',cols);
                      coll[i].setAttribute('rowspan',rows);


                      }
                      else if(coll[i].tagName=='IMG')
                      {
                      coll[i].style.cssText="";
                      coll[i].className='';
                      }
                      else
                      {
                      coll[i].clearAttributes();
                      coll[i].style.cssText="";
                      }
                      if(coll[i].tagName=='TABLE')
                      coll[i].className=allowClaPrefix+"tab_1";
                      }
                      ieClearStyles(coll[i],count+1);
                      }
                      }
                      }
                        0
                        простите, а чем SPAN не угодил?
                          0
                          Просто при переносе из ворда очень много лишних стилей переносится именно чере SPAN. И когда их на 1 предложение до 12 штук разной степени вложенности - очень сложно автоматом вычистить то, что нужно. А так можно и SPAN оставить - я против него лично ничего не имею :). Но мне в 99% этот тег не нужен.
                            0
                            ясно :-)
                            а я уж испугалась, что пропустила момент, когда и этот тег объявили невалидным
                        +2
                        Классно. Респект.

                        Однако, клиент может оказаться еще более «продвинутым» — доберется какой-нибудь «программист» до этого нехитрого ресета, обнаружив в нем корень всех своих проблем, и сделает ему кильдык. Отрапортует потом менеджеру, что всё, мол, можно дальше работать, теперь ваша разметка заработает.

                        По статистике (я работал в двух компаниях) 100% сайтов, ушедших на сопровождение к самим клиентам (с любыми админками, висивигами, базами данных, цэ-эм-эсами), возвращаются через короткий срок неоперабельными — после плодотворных усилий «спецов», по дешевке решающих подобные «проблемы», стройная система разрушается и сайт перестает работать в привычном смысле этого слова. Беда зачастую состоит еще и в том, что в стремлении «сэкономить» (а именно им обусловлен отказ от профессиональной поддержки) такие клиенты продолжают обращаться к «спасителю», а не к авторам оригинальной системы. «Веб-мастер» сдельно создает новые страницы и правит старые — пользуясь обычно статическим HTML или иногда жесткими конструкциями if(), вписываемыми прямо в исполняемый файл движка (безотносительно от его архитектуры). Когда клиент возопит, что сайт окончательно перестал работать, вернется к авторам и бросит им в лицо требование сделать всё «как было», исправлять что-то уже бывает поздно — гораздо быстрее можно воссоздать сайт с нуля, чем откатить неизвестное количество неизвестных изменений.

                        То есть я что хочу сказать — предложенный метод весьма хорош, если клиенту иногда самому надо что-то добавить на сайт, а у исполнителя системы нет времени контролировать каждое изменение. Но полностью защитить систему от дурака такое нововведение не сможет, увы.
                          +1
                          Ага, согласен по всем пунктам. Способов довольно много, главное не отрицать существования проблемы, как делают некоторые ))
                        • НЛО прилетело и опубликовало эту надпись здесь
                            0
                            Видимо кто-то вам удалил возможность использовать нежелательные тэги и атрибуты по сходному принципу ))
                            • НЛО прилетело и опубликовало эту надпись здесь
                                +1
                                Это было бы чудесно, но к сожалению не всегда выполнимо.
                          • НЛО прилетело и опубликовало эту надпись здесь
                              +4
                              Да и, кстати же, первое изменение, которое захочет внести клиент (без шуток) - это в новостях написать «СКИДКИ!!!» жирным красным Comic Sans, и чтоб по центру. Без этого не менее половины из них свой сайт не ценят.
                                0
                                Да, конечно захотят. Но это задача дизайнера сразу предусмотреть несколько информационных блоков. Кликаешь на кнопку - сразу вставляется нужный код, что-то вроде div class=r4_attention Здесь важное сообщение /div и в классе прописаны и размер шрифта, и его цвет и т.д. То что у пользователя нет возможности сделать какие-то вещи - это значит не понял исполнитель заказчика. А таких блоком модет быть много:
                                1. 2 колонки
                                2. небуллетированные списки
                                3. специальное форматирование (фото+имя+e-mail) для списка сотрудников

                                Вобщем, надо придусматривать изначально действия.
                                  0
                                  Просто до получения контроля над сайтом клиент стучал *чем-то* по столу и требовал соблюдения фирменного стиля. Что позволено Юпитеру, как водится...
                                    +2
                                    ... быку, собственно, не положено! Безусловно. При должном упорстве сломать и испортить можно все. Но когда есть возможность дать готовые шаблоны, которые помогут "не навредить".

                                    Проблема у клиентов одна - у него нет человека с чувством вкуса. Ну не может серетарь писать нормальные тексты и обрабатывать картинки - если бы могла - уж давно бы работала на другом месте.

                                    Я к тому, что лучше сайт поддерживать. Уж клиенту выгоднее платить студии 6000р. в месяц за 2 новости и 3 позиции в каталоге, чем нанимать отдельного человека. И сайт хороший, и у студии есть постоянные деньги - всем хорошо.
                                  +1
                                  Яркий пример http://kld-m.ru/
                                  0
                                  Не знаю, по-моему, клиент в праве делать что хочет со своим сайтом. Это как запрещать изменять wallpaper, или, скажем панели — можно-то оно можно, вот только нужно ли. Пусть делают, что хотят — лишь бы им самим было хорошо. А не вывешивать лишних инструментов здесь, пожалуй, уже правильный способ. Хотят сделать «красиво» — пусть учат HTML/CSS и вбивают ручками.

                                  Да и, кстати, не убьёт ли «font-family:expression (this.parentNode.currentStyle['fontFamily']);» валидность CSS?
                                    +1
                                    Любой expression убьет валидность CSS. Я всегда выношу стили для IE в отдельный файл с помощью Conditional Comments.
                                      0
                                      Тут палка о двух концах. С одной стороны имеет. А с другой - у меня есть некоторые кол-во работ, которые я не рискну показать потенциальному заказчику. Именно по причине того, что они были испорчены в процессе эксплуатации.

                                      В обсуждаемой в статье подходе, имхо, есть одна принципиальная ошибка. Клиент делает большой красный текст, но потом его не видит. Что он думает? Правильно. Не работает. И начинает трясти разработчика на предмет "какого фига". И, по большому счету, правильно делает. Поэтому я считаю, что не надо такие возможности вообще предусматривать. Минимальные возможности типа выделения жирным + готовые шаблоны. И все. О чем вы, собственно и сказали :)
                                        0
                                        В конце статьи есть небольшая, но важная ремарка. Клиента надо обеспечить необходимым инструментарием изначально, а что именно это будет - классы или шаблоны - решать вам.
                                          +1
                                          Я бы сказал, что его не надо обеспечивать лишним инструментарием :) Дабы не искушать.
                                      +1
                                      Если у клиента элементарно отсутствует вкус, то бороться с этим только себе дороже. Это один из тех случаев, когда дураку уже проще дать, что он хочет, забрать деньги и жить счастливо.

                                      Представте, если бы производители боролись с тем, что они считают неуместным применительно к их продукции? Хочешь закачать рингтон, а вот нет! Исполнитель не тот. Обои на рабочий стол? Нееет, сильно откровенная барышня. Литые диски на авто? Сильно дерзкие, не сочетаются с имиджем нашей марки.

                                      Я в таком мире жить не хочу.

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

                                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                      Самое читаемое