Нормализация в HTML и CSS
Нормализация в HTML и CSSВопрос
Какие есть формы нормализации, почему я должен знать о них при создании HTML и CSS контента?
Ответ
Нормализация — то, о чем вы должны знать, если вы разрабатываете HTML страницы с таблицами стилей CSS в UTF-8 (или в любой другой кодировке Unicode), особенно если вы имеете дело со скриптом, который в тексте использует ударения или другие диакритические знаки.
Какие есть формы нормализации?
В Unicode можно показывать тот же текст с разными последовательностями символов. Например, возьмем венгерское слово világ. Четвертая буква может храниться в памяти как составленная U+00E1 МАЛЕНЬКАЯ ЛАТИНСКАЯ БУКВА A С УДАРЕНИЕМ (один символ) или как разложенная последовательность U+0061 МАЛЕНЬКАЯ ЛАТИНСКАЯ БУКВА A за которой следует U+0301 УДАРЕНИЕ (два символа).
Стандарт Unicode позволяет любую из этих альтернатив, но требует, чтобы обе рассматривались как идентичные.
Есть четыре формы нормализации указанные стандартом Unicode: NFC, NFD, NFKC и NFKD. C означает составленные, и D означает разложенные. K означает совместимость. Для улучшения совместимости, W3C рекомендует использовать NFC нормализованный текст на Веб страницах.
Что мне нужно знать о нормализации?
К сожалению, нормализация не всегда используется до сравнения контента. Особенно важно использование селекторов и имен классов или идентификаторов в HTML и CSS. Если слово világ используется в составленной форме в HTML (например <span>
), но в разложенной форме в CSS (например .világ { font-style: italic; }
), то потом селектор не будет соответствовать имени класса.
Это означает, что при создании контента вы должны убедиться, что селекторы и класс или идентификаторы такие же символ-к-символу. Это особенно вероятно тогда, когда разметка и CSS разрабатываются или обслуживаются разными людьми.
Лучший способ убедиться, в соответствии — использовать одну отдельную форму Unicode нормализации для всего контента, который разрабатывается. Как мы уже говорили выше, W3C рекомендует NFC.
Большинство клавиатур для европейских языков уже выводят текст в NFC, но это менее вероятно в случае, если вы имеете дело со многими неевропейскими языками.
В некоторых случаях ваш редактор может позволить вам сохранить данные в форме нормализации на выбор. На изображении ниже показан вариант для создания особой формы нормализации по умолчанию при открытии новых файлов в Dreamweaver (избранная NFC). Вам показан подобный выбор при сохранении документа.
Как я могу проверить страницы на наличие ошибок?
Вы можете выяснить содержат ли страницы HTML имена классов и идентификаторы, которые не нормируется согласно NFC, используя Контроллер W3C Интернационализации.
Если у вас проблемы, вы должны найти редактор или инструмент для преобразования, который позволяет указать форму нормализации, и использовать его для повторного сохранения страницы.
Дополнительные материалы
Приступая к работе? Представляем Наборы Символов и Кодирование
Пособие, Обработка кодирования символов в HTML и CSS
Ссылки по теме, Разработка HTML и CSS
- Символы
- Обработка нормализации
ES6: символы изнутри — CSS-LIVE
Перевод статьи ES6 Symbols in Depth с сайта ponyfoo.com, опубликовано на css-live.ru с разрешения автора — Николаса Беваквы.
Приветствую! Милости просим в «ES6 — надо же, еще один выпуск — изнутри». Если не представляете, как тут очутились или вообще что такое ES6, рекомендую ознакомиться с краткой историей инструментария ES6. Затем изучить деструктирование, литералы шаблона, стрелочные функции, оператор расширения и оставшиеся параметры, улучшения в литералах объекта, новый «сахарок» — классы поверх прототипов, let
, const
и «Временную мёртвую зону», а также итераторы и генераторы. Ну а сегодня поговорим о символах.
Как и в прошлых статьях, рекомендую вам установить Babel и повторять за мной, копируя примеры с помощью интерактивной оболочки REPL, либо командной строки babel-node и файла. Это поможет гораздо лучше усвоить идеи, обсуждаемые в серии. Если вы не из тех, кто любит устанавливать что-либо на свой компьютер, то вам есть смысл залезть на CodePen и кликнуть иконку с шестерёнкой для JavaScript — у него есть препроцессор Babel, который с лёгкостью позволяет опробовать ES6. Ещё одна довольно полезная альтернатива, это использовать онлайновый REPL для Babel — он показывает скомпилированный ES5-код справа от ES6-кода, чтобы быстро сравнить.
Пока мы не начали, позвольте беззастенчиво попросить вашей поддержки, если вы наслаждаетесь моей серией «ES6 изнутри». Ваши взносы пойдут на хостинг сайту, мне на еду, на то, чтоб я не отставал от графика, и на то, чтобы Pony Foo оставался поистине источником джаваскриптовых вкусняшек.
Спасибо, что выслушали, а теперь перейдём к символам! Мы уже познакомились вскользь с символами в статьях про итераторы и генераторы, так можете заглянуть туда.
Что такое символы?
Символы — новый примитивный тип в ES6. Как по мне, так они ужасно похожи на строки. Как и в случае с числами и строками, вместе с символами вводится соответствующий объект-обёртка Symbol
.
Можно создавать наши собственные символы.
var mystery = Symbol()
Заметьте, что оператор new
отсутствует. Он даже выбрасывает TypeError
, когда мы пробуем его с Symbol
.
var oops = new Symbol() // <- TypeError
В отладочных целях символы можно описывать.
var mystery = Symbol('это наглядное описание')
Символы неизменяемы. Так же, как числа или строки. Однако, заметьте, что символы уникальны, в отличие от примитивных чисел или строк.
console.log(Symbol() === Symbol()) // <- false console.log(Symbol('foo') === Symbol('foo')) // <- false
У символов тип symbol.
console.log(typeof Symbol()) // <- 'symbol' console.log(typeof Symbol('foo')) // <- 'symbol'
Есть три вида символов — и обращаться к каждому из них нужно по-своему. Рассмотрим каждый из них и потихоньку выясним, что всё это значит.
- Доступ к локальным символам можно получить с помощью ссылки на них напрямую.
- Можно разместить символы в глобальном регистре и получить к ним доступ сквозь владения (realms).
- «Известные» символы не ограничены владениями – но нет возможности их создать, равно как их нет и в глобальном регистре.
Что ещё за владения, спросите вы? Владение — так на жаргоне спецификаций называют любой контекст исполнения, например, страницу, на которой запускается ваше приложение, или <iframe>
на странице.
«Всеконтекстный» регистр символов
Есть два метода для добавления символов к вcеконтекстному регистру символов. Symbol.for(key)
и Symbol.keyFor(symbol)
. Что они делают?
Symbol.for(key)
Этот метод ищет ключ (key
) во всеконтекстном регистре символов. Если символ с этим ключом есть в глобальном регистре, то этот символ и вернется. Если символ с таким ключом не найден в регистре, то он создаётся. Т.е. Symbol.for(key)
всегда возвращает один и тот же результат. В коде ниже первый вызов Symbol.for('foo')
создаёт символ, добавляет его в регистр и возвращает его. Второй вызов возвращает тот же символ, поскольку key
уже в регистре — и связан с символом, возвращённым первым вызовом.
Symbol.for('foo') === Symbol.for('foo') // <- true
Это с трудом вяжется с тем, что символы, как мы знаем, уникальны. Однако, глобальный регистр символов отслеживает символы по ключу.
description
), когда создаются символы, попадающие в регистр. Также учитывайте, что эти символы глобальнее чем что бы то ни было в JS, так что ведите себе прилично и используйте префикс, а не просто называйте символы 'user'
или подобным общим названием.Symbol.keyFor(symbol)
Если взять символ symbol
, Symbol.keyFor(symbol)
возвращает ключ, который был связан с symbol
при добавлении символа в глобальный регистр.
var symbol = Symbol.for('foo') console.log(Symbol.keyFor(symbol)) // <- 'foo'
Насколько широка всеконтекстность?
Всеконтекстность означает, что символы в глобальном регистре не ограничены контекстом исполнения кода. Вероятно, кусок кода лучше это прояснит. Это просто означает, что регистр общий для разных контекстов исполнения.
var frame = document. createElement('iframe') document.body.appendChild(frame) console.log(Symbol.for('foo') === frame.contentWindow.Symbol.for('foo')) // <- true
«Известные» символы
Успокою вас: на самом деле никакие они не известные. Отнюдь нет. Ещё несколько месяцев назад я и понятия не имел об этих вещах. Почему же их тогда называют «известными»? А потому, что они встроены в JavaScript и используются для управления частями языка. Они были недосягаемыми для пользовательского кода до ES6, но теперь это не так.
Отличный пример «известного» символа был у нас как-то на Pony Foo: известный символ Symbol.iterator
. Мы использовали его для определения метода @@iterator
в объекте, который придерживается протокола «Итератор». Есть ещё список известных символов на MDN, но на момент написания этой статьи описано всего несколько.
Один из известных символов, описанный в данный момент — Symbol. match
. Согласно MDN, можно установить свойству Symbol.match
регулярных выражений значение false
и заставить их при сравнении вести себя, как литералы строки (вместо регулярных выражений, которые не особо дружат с .startsWith
, .endsWith
или .includes
).
Эта часть спецификации ещё не реализована в Babel — полагаю потому, что игра не стоит свеч — но по идее, это должно быть как-то так.
var text = '/foo/' var literal = /foo/ literal[Symbol.match] = false console.log(text.startsWith(literal)) // <- true
В чем прикол делать так вместо того, чтобы привести литерал (literal
) к строке — загадка для меня.
var text = '/foo/' var casted = /foo/.toString() console.log(text.startsWith(casted)) // <- true
Наверное, наличие этого символа в языке оправдано какими-то важными соображениями производительности, но не думаю, что это станет основой front-end разработки в ближайшее время.
Тем не менее
Symbol.iterator
на самом деле очень полезный, уверен, что и другие известные символы также полезны.
Заметьте, что известные символы уникальны, но общие для разных контекстов исполнения, даже при том, что они не доступны в глобальном регистре.
var frame = document.createElement('iframe') document.body.appendChild(frame) console.log(Symbol.iterator === frame.contentWindow.Symbol.iterator) // <- true
Не доступны в глобальном регистре? Неа!
console.log(Symbol.keyFor(Symbol.iterator)) // <- undefined
Хотя, возможности обратиться к ним статически откуда угодно должно быть вполне достаточно.
Символы и итераторы
Всё, что работает с протоколом «Итерируемый» явно игнорирует все символы кроме Symbol.iterator
, который показывает, что объект итерируемый, и определяет, как его перебирать.
var foo = { [Symbol()]: 'foo', [Symbol('foo')]: 'bar', [Symbol.for('bar')]: 'baz', что: 'угодно' } console.log([...foo]) // <- []
Метод Object.keys
из ES5 игнорирует символы.
console.log(Object.keys(foo)) // <- ['что']
То же касается и JSON.stringify
.
console.log(JSON.stringify(foo)) // <- {"что":"угодно"}
Ну что, тогда for..in
? Неа.
for (let key in foo) { console.log(key) // <- 'что' }
А, Object.getOwnPropertyNames
. Тоже нет! — Но близко.
console.log(Object.getOwnPropertyNames(foo)) // <- ['что']
Вам нужно явно искать символы, чтобы к ним обратиться. Они как нейтрино в JavaScript. Для их обнаружения воспользуйтесь Object.getOwnPropertySymbols
.
console.log(Object.getOwnPropertySymbols(foo)) // <- [Symbol(), Symbol('foo'), Symbol.for('bar')]
Магическая завеса с символов спадает, и теперь можно перебирать символы с помощью цикла for..of
, чтобы наконец найти сокровища, которые они охраняли. Надеюсь, в вашем случае эта находка окажется поинтереснее, чем в примере ниже.
for (let symbol of Object.getOwnPropertySymbols(foo)) { console.log(foo[symbol]) // <- 'foo' // <- 'bar' // <- 'baz' }
Зачем символы мне?
Есть несколько разных применений для символов.
Конфликты имён
С помощью символов можно избежать конфликта имён в ключах свойств. Это важно, когда речь идет о паттерне «объект — это ассоциативный массив», с которым то и дело случается досадный облом, как только кто-то (случайно или по злому умыслу) переопределяет нативные методы.
«Приватность»?
Символы невидимы для всех reflection-методов до ES6. В некоторых случаях это может быть полезно, но они не приватны при всём желании, как мы только что продемонстрировали с помощью API Object.getOwnPropertySymbols
.
С другой стороны, тот факт, что символы приходится искать специально, означает, что они полезны в сценариях, где нужно определить метаданные, которые не должны быть частью итерируемых последовательностей для массива или любых итерируемых объектов.
Определение протоколов
Думаю, наибольшая польза от символов именно в том, для чего реализации ES6 их используют: определение протоколов — как Symbol.iterator
, определяющий, как может итерироваться объект.
Представьте, например, библиотеку типа dragula
, определяющую протокол через Symbol.for('dragula.moves')
, где можно было бы добавлять метод этого Symbol
к любым DOM-элементам. Если бы DOM-элемент подчинялся протоколу, то dragula
могла бы вызвать пользовательский метод el[Symbol. for('dragula.moves')]()
, чтобы решить, можно ли этот элемент двигать.
Таким образом, логика перетаскиваемых dragula
элементов переносится из одного места для целого объекта drake
(параметр options для экземпляра dragula
) на каждый отдельный DOM-элемент. Это упрощает работу со сложными взаимодействиями в больших проектах, поскольку логика передаётся отдельным нодам в DOM, а не сосредоточена в одном методе options.moves
.
P.S. Это тоже может быть интересно:
html — в iOS 9 удалена возможность изменять определенные цвета символов с помощью CSS
спросил
Изменено 6 лет, 3 месяца назад
Просмотрено 6к раз
Мы использовали различные символы, такие как галочки (✔) на нашем веб-сайте, и только что заметили, что с выпуском iOS 9, Safari и другие браузеры были обновлены, чтобы не учитывать атрибут цвета. Такое же поведение наблюдается как в Safari, так и в Chrome на iOS 9.
test ✔дел { цвет: #ff0000; -webkit-внешний вид: нет; }
https://jsfiddle.net/afb14b2k/1/
Приведенный выше пример отлично отображается на других платформах (например, OS X). Есть ли известный обходной путь, чтобы заставить это работать на iOS 9?
Редактировать: похоже, это относится только к определенным вариантам галочек (и другим вариантам символов). В данном случае мы использовали жирную галочку (U+2714). При переключении на обычную галочку (U+2713) iOS не применила к ней никакого форматирования, и мы смогли применить к ней собственный цвет.
- html
- ios
- css
- сафари
- ios9
2
В iOS 9 U+2714 HEAVY CHECK MARK
включен в набор символов эмодзи Apple. Как и другие смайлики, он отображается как полноцветное растровое изображение, а не как одноцветный векторный глиф, поэтому вы не можете изменить его цвет с помощью CSS. (На самом деле нет никакой гарантии, что галочка вообще будет черной. Другие платформы рисуют ее разными цветами!)
Чтобы iOS отображала галочку как обычный текст, который можно перекрасить, необходимо использовать символ U+FE0E VARIATION SELECTOR-15
. Если вы поместите этот символ выбора варианта сразу после ✔, iOS будет использовать обычную текстовую версию (✔︎) вместо версии с эмодзи (✔). В OS X нет варианта эмодзи, поэтому они выглядят одинаково, но в iOS варианты выглядят немного иначе:
В HTML вы можете добавить символ, поместив ︎
сразу после ваших галочек.
раздел { красный цвет; }
<дел> ✔ без селектора вариантов
✔︎ с селектором вариантов дел>
6
Если вы пытаетесь стилизовать элемент с помощью CSS-after, вот как это сделать, чтобы значок стал зеленым в iOS. Только с «✔» iOS не изменит цвет значка.
.myElement: после { цвет:зеленый; содержимое: "✔\fe0e"; }
Зарегистрируйтесь или войдите в систему
Зарегистрируйтесь с помощью Google
Зарегистрироваться через Facebook
Зарегистрируйтесь, используя электронную почту и пароль
Опубликовать как гость
Электронная почта
Обязательно, но не отображается
Опубликовать как гость
Электронная почта
Требуется, но не отображается
HTML Объекты символов CSS, символы и коды
Объекты символов HTML копировать и вставлять.