Блог Игоря Шевченко

Text-transform и копирование 24 января 2019

Что происходит при копировании текста с text-transform.

Alphabet, Le Bistronome (CC BY-NC 2.0)

В CSS есть свойство text-transform. С помощью него можно менять регистр текста: можно преобразовать текст в ПРОПИСНЫЕ, строчные или Капитализировать Только Первые Буквы Слов. Это делается значениями uppercase, lowercase и capitalize, соответственно. Помимо них есть значения full-width и full-size-kana, про которые мы в этот раз говорить не будем.

Примеры использования text-transform

Выше приведен пример использования свойства text-transform. Попробуйте скопировать любой из них и вставить куда-нибудь. Результат будет отличаться в зависимости от вашего браузера:

  • Если у вас браузер на WebKit или Blink (Chrome, Safari, Opera 15+, Яндекс.Браузер и вскоре даже Edge), то вставится измененный текст — тот, который вы видите в браузере.
  • В остальных браузерах (Firefox, IE и пока Edge) вставится исходный текст — тот, который написан в HTML.

Стандарт до недавнего времени не определял, какое поведение является верным, поэтому оно стало предметом споров в баг-трекерах. Баг для Firefox завели еще в 2000 году, баг для WebKit с противоположным смыслом — в 2010. У сторонников обоих вариантов есть аргументы.

Главный аргумент за копирование измененного текста, как в WebKit — соответствие ожиданиям пользователя. Человек не может понять, в результате чего текст отображается заглавными буквами. Может быть, он прописан таким образом в исходном коде, а может быть, к нему применено text-trasform: uppercase. Если пользователь будет копировать текст в верхнем регистре, а потом вставлять его и иногда видеть что-то другое, ему будет казаться, что веб сломался и глючит.

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

В 2016 году за этот вопрос взялась Рабочая группа CSS (CSSWG). При обсуждении выделили основные сценарии использования text-transform:

  • p::first-line { text-transform: uppercase } — первую строку набирают прописными буквами, как это иногда делают в англоязычной художественной литературе. В этом случае лучше копировать исходный текст, иначе он будет выглядеть странно.
  • abbr { text-transform: lowercase; font-variant: small-caps } — аббревиатуры в тексте набирают капителью. Свойство font-variant: small-caps берёт специальное начертание для капители из шрифта или отображает строчные буквы как прописные, только уменьшенного размера, если их нет. В этом случае тоже лучше копировать исходный текст, иначе аббревиатуры будут набраны строчными буквами.
  • h1 { text-transform: uppercase } — стилизуют заголовки с помощью прописных букв. Здесь применимы аргументы за оба варианта поведения.
  • em { font-style: normal; text-transform: uppercase } — используют прописные буквы для выделения важных фрагментов. Здесь тоже применимы оба аргумента.

В результате обсуждений в рабочей группе, в 2018 году было принято решение: дополнить стандарт CSS указанием, что свойство text-transform не должно влиять на копируемый текст.

Коммит, который вносит изменения в стандарт.

Сейчас баг в Firefox закрыт как «wontfix», баг в WebKit по-прежнему открыт. Но уже можно надеяться, что скоро его поправят, и копирование текста с text-transform начнет работать во всех браузерах одинаково.

Изначально этот пост был опубликован на Веб-стандартах. Спасибо Вадиму Макееву за полезные замечания и редактуру.

1 комментарий

Гиперобщительный магазин 3 декабря 2017

Недавно я сделал заказ в местном интернет-магазине. Через три часа заехал к ним на склад и забрал его. За эти три часа магазин прислал мне 9 электронных писем и 8 смс.

Вот эти сообщения. Смс нужно читать сверху вниз, а письма снизу вверх.

Я не стал убирать название магазина и другие подробности, но это не реклама и не критика конкретного магазина. Как писал Антон Жиянов, магазин вообще не виноват, они просто поставили движок, который из коробки работает таким образом. Тем не менее, я предлагаю подумать, сколько из этих сообщений можно было бы убрать или сделать необязательными в хорошем движке.

Кассовый чек и письма от платежного шлюза. Закон об онлайн-кассах, который начал действовать эти летом, требует обеспечить возможность отправки кассового чека на покупки в интернете по электронной почте. Только обеспечить возможность — они не обязаны отправлять чек, если покупателю он не нужен. Некоторые сервисы это учитывают, а некоторые, как в этом случае, требуют обязательно указать адрес для чека. А потом пользуются этим адресом, чтобы отправить еще пару писем от себя. Если сделать ввод почты опциональным, то это уже −3 письма.

Регистрация. При заказе я дважды вводил код из смс — первый раз для регистрации на сайте, второй раз для подтверждения заказа. Сейчас в хороших интернет-магазинах уже не требуют зарегистрироваться перед заказом, регистрация происходит по ходу его оформления. Если бы в этом магазине было так же, то достаточно было бы одного подтверждения. −1 смс.

Пароль. В уведомлениях о регистрации пришли пароли в открытом виде. Это не означает, что они так и хранят их, но всё равно это плохая практика. Отправлять пароли небезопасно, потому что письма и смс могут быть прочитаны человеком посередине или, что немного более вероятно, любым, кто получит доступ к почтовому ящику или телефону. Больше в этих сообщениях ничего полезного нет, убираем их: −1 письмо, −1 смс.

Ненужные этапы. Заказ на сайте разбит на две части. Сперва я оформляю заказ и резервирую товар, а потом мне предлагают его оплатить. Я оплачиваю сразу, поэтому для меня смысла в этом промежуточном этапе нет: −1 письмо, −1 смс. Еще один ненужный этап — «заказ скомплектован», когда его весь собрали в одном месте, но забрать пока что нельзя. Непонятно, что я должен делать с этой информацией. −1 письмо.

Очевидные этапы. Я сам оплачиваю заказ на сайте и забираю его в магазине, поэтому я и так знаю о том, что эти события произошли. Убираем избыточные уведомления: −2 письма, −2 смс.

Дублирование. В почте осталось последнее письмо — о том, что заказ доставлен. Вот это очень полезная информация, но я и так об этом узнал из смс. Давайте уберем и это письмо, тогда можно будет даже не запрашивать у пользователей почту. −1 письмо.

Код подтверждения. Когда я забираю покупку, мне отправляют смс с кодом подтверждения. Молодцы, проверяют, чтобы какие-нибудь жулики не пришли и не взяли мой оплаченный заказ. Но этот код можно было сразу вставить в смс о том, что заказ доставлен. Плюсов у этого варианта куча: не нужно ждать смс на кассе, можно попросить кого-то другого забрать заказ и сказать ему код, можно записать куда-нибудь код, когда садится телефон. −1 смс. А если я это сообщение всё-таки как-то потеряю, то тогда уже можно по запросу прислать новое.

В итоге осталось два нужных сообщения: подтверждение телефона при заказе и сообщение о том, что заказ доставлен. Если бы мне прислали только их, я бы вообще сразу же забыл, что были какие-то смс. Но когда сайт бомбардирует уведомлениями по двум каналам, это сложно не заметить, и это немного напрягает. 

Проблема здесь в том, что если смотреть со стороны этой системы, то у нее тоже есть своя логика работы. Изменилось состояние заказа — уведомляем. Известны и почта, и телефон — пишем в оба канала. Нужно подтвердить кодом из смс — отправляем, несмотря на то, что его уже отправляли полминуты назад. Разработчики должны хорошо владеть внимательностью и эмпатией, чтобы увидеть, что в результате получается что-то не то.

Нет комментариев

Неверное имя пользователя или пароль 26 ноября 2017

Практически любой сайт, если попытаться авторизоваться с неверными данными, выдаст стандартное сообщение: «Неправильное имя пользователя или пароль». Если вы разрабатываете какой-то сайт, то скорее всего, он говорит то же. Считается, что такой расплывчатый текст усложняет работу хакерам, которые взламывают аккаунты на сайте. Взломщики будут тратить много времени на попытки подобрать пароль к пользователям, которые даже не зарегистрированы. Простым людям от этого менее удобно, но это обычный компромисс между удобством и безопасностью.

В реальности всё это работает не совсем так успешно. К примеру, недавно я забыл пароль от сервиса Grammarly. Изначально при входе я увидел типичную надпись.

Пошел восстанавливать пароль, там сообщение тоже расплывчатое: если вы зарегистрированы, то письмо отправлено, но если такого аккаунта нет, то ничего не отправлено.

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

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

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

Если вы хотите сделать авторизацию на сайте безопаснее, есть более эффективные способы:

  1. Ограничивайте количество попыток ввода неправильного пароля, а потом показывайте капчу или блокируйте.
  2. Помогайте пользователю выбрать надежный пароль с помощью индикаторов сложности пароля.
  3. Добавьте двухфакторную аутентификацию.
  4. Зарегистрируйте логины-ханипоты (вроде admin@yoursite.com) и блокируйте тех, кто пытается в них войти.

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

4 комментария

Как писать интерфейсные надписи 10 сентября 2017

Представьте себе разработчика Петра, который с утра пришел на работу и увидел в Джире такую задачу:

Добавить на страницу с отчетом возможность отправить csv-версию отчета на почту текущему пользователю

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

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

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

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

Надписи должны быть точными

Иногда тянет написать какой-то обобщенный текст и использовать его во всех возможных ситуациях. Например, для всех ошибок выводить сообщение «Что-то пошло не так».


Это скриншот интерфейса электронной регистрации на авиарейс из блога Артемия Лебедева. Если бы разработчики указали, в каком виде они хотят получить номер телефона, Артемий и другие пассажиры тратили бы намного меньше времени на попытки угадать формат.


Это пример из гугловских гайдлайнов. Точное сообщение помогает людям быстрее увидеть ошибку во введенных данных.


Посмотрите, как Трелло обрабатывает невалидные почтовые адреса. Они не поленились вместо простого сообщения «Введите правильный емейл» разобрать случаи и указать, в какой части адреса проблемы. Давайте быть как Трелло и разбирать случаи, чтобы пользователям меньше приходилось разбираться самим.

Надписи должны быть полезными

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

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


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


Ошибка авторизации в Мейлчимпе. Сайт точно указывает, в чем проблема — в несуществующем юзернейме или неправильном пароле. Но помимо этого, он сразу же предлагает пользователю следующее логичное действие и показывает прямо в сообщении ссылку на восстановление юзернейма или пароля.


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

Надписи должны быть человечными

При разработке систем мы обычно глубоко погружаемся в подробности их реализации и думаем о них уже не в тех терминах, которые используют обычные люди. Если начать их грузить терминологией и подробностями, они ничего не поймут. В английском языке это называют словом Nerdview.


Это канадский транспортный терминал. С точки зрения обычного человека, терминал нужен, чтобы класть деньги на карточку, а потом расплачиваться ею в автобусе. С точки зрения программистов, этот терминал делает запросы к биллинговому серверу, которые могут иметь статусы «Выполнен» и «Ошибка». Программисты понимают, что значит «Запрос выполнен», а для нормальных людей это сообщение не несет никакого смысла.


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


Удивительный факт: пользователи никогда не считают себя или других людей «пользователями». На сайте с митапами это понимают, поэтому пишут не просто «10 пользователей идут на это событие», а указывают, что это за люди. Например, на встречу клуба читателей собирается 21 книжный червь.


Ну и совсем плохо, если пользователь видит техническое сообщение вроде NullReferenceException was thrown. Такие сообщения помогают при отладке, но на продакшне их нужно отключать.

Надписи должны быть короткими

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


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

Надписи должны быть самодостаточными

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

В бюро Горбунова это называют «взглядом новичка». Каждое возможное состояние должно иметь смысл с точки зрения человека, который забыл всё, что видел до этого. Если какая-то надпись непонятна сама по себе, нужно добавить в нее больше контекста и информации.


Еще лучше, когда самодостаточны даже отдельные элементы на экране. Например, маковские гайдлайны требуют не писать на кнопках просто «Да», «Нет», «Ок», а указывать совершаемое действие: «Сохранить» или «Удалить». Тогда решение получится принять быстрее, а вероятность нажать не на ту кнопку будет меньше.

Надписи должны быть уместными

Об этой проблеме хорошо написано в статье «Опаньки! Я сломал вам жизнь :)» (цитата из перевода с Хабра):

Ещё не угасла надежда на слабый сигнал Wi-Fi в аэропорту, на заряд батареи, который вот-вот заставит ноутбук вырубиться — а розетку здесь найти та ещё задача — и на то, что письмо клиенту на миллион долларов вроде ушло. И в этот момент «пожалуйста, заработай» вылезает приводящее в шок сообщение: «Упс». Как в некоторые бросающие в дрожь моменты фильма «Американский психопат» это не очень различимое, бесстрастное сообщение от почты Gmail вонзает кинжал точно в моё сердце, мгновенно порождая отчаяние — что же пошло не так?

Сейчас модно вставлять в тексты микрокопию — небольшие забавные тексты, которые по задумке должны приятно удивить или повеселить пользователя. Например, сервис почтовых рассылок Мейлчимп хвалит пользователя, дописавшего письмо, говоря ему «High Fives!» и показывая гифку с обезьяньей рукой. А если попытаться зарегистрироваться в Тумблере под уже занятым именем, появится сообщение «That's a good one, but it's taken».

Мне нравятся такие штуки, но с ними нужно быть очень аккуратными. Текст должен соответствовать тому, что чувствует пользователь. Слишком веселое сообщение об ошибке будет восприниматься как издевательство. У Мейлчимпа есть справочник по тональности для разных случаев. Пользуйтесь им.

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

Надписи должны быть целостными


Это скриншоты из старого Дропбокса. История версий файла в трех местах называется по-разному, и это будет путать пользователя. Если он запомнил заголовок «Version History», то он будет искать его в меню, где вместо этого написано «Previous versions». Будьте в курсе терминологии вашей системы и везде используйте единые понятия.

Целостность важна не только в терминологии, но и в деталях. Если все валидационные сообщения заканчиваются точкой, не забудьте поставить ее в очередном валидационном сообщении. Лично я не люблю писать «Вы» с большой буквы, но если так пишут на всем остальном сайте, то я не буду поднимать бунт и писать свой отдельный текст по-другому.


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

Надписи должны быть грамотными

Это очевидно, но ошибки и опечатки встречаются у всех. Проверяйтесь. Хорошо, если ваши IDE или линтер умеют находить ошибки в текстах.

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

Отдельная проблема есть с динамическими сообщениями вроде «22 файлов отправлено». Чтобы они были формально корректными, в них часто меняют формулировку на что-нибудь вроде «Файлов отправлено: 22». Это звучит очень неестественно, лучше написать по-человечески, разобрав возможные случаи (это легко).

Надписи должны быть необходимыми

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

Делайте работу за пользователя. В примере с Артемием Лебедевым и форматом телефона на сайте авиакомпании можно было просто приводить номер к нужному виду внутри системы.

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

Домашнее задание

Повторю список правил еще раз, надписи должны быть:

  1. Точными
  2. Полезными
  3. Человечными
  4. Короткими
  5. Самодостаточными
  6. Уместными
  7. Целостными
  8. Грамотными
  9. Необходимыми

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

  • Эта возможность доступна только платным подписчикам.
  • (при сбросе пароля) Ваш временный код уже использован или истек!
  • Duplicate entry "ivan@gmail.com" for key "ixemail"
  • Пост не может быть удален.
  • Ошибка авторизации: вы уже авторизованы.
9 комментариев

Быстрые напоминания в Слаке 15 марта 2017

Я работаю в географически распределенной команде. Часть наших разработчиков сидит в Техасе, а я вместе с другими разработчиками нахожусь в Челябинске. Для общения мы используем Слак.

В Слаке много удобных фишек, но самыми недооцененными мне кажутся быстрые напоминалки.  В списках советов для пользователей Слака им уделяется столько же внимания, сколько команде /shrug ¯\_(ツ)_/¯

Напоминалки прячутся под кнопкой Remind me about this возле каждого сообщения.

Слак предлагает готовые временные интервалы Слак предлагает готовые временные интервалы

Слакбот подтверждает установку напоминалки Слакбот подтверждает установку напоминалки

Время пришло, и слакбот прислал сообщение в личку Время пришло, и слакбот прислал сообщение в личку. Иногда я слишком занят в этот момент, и тогда прошу слакбота написать еще раз попозже

На мобильниках это тоже есть.

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

/remind [@имя или #канал или me] [о чем напомнить] [когда напомнить]

Я обычно пишу описание на английском, тогда команда выглядит как просьба на естественном языке:

/remind me to fix the bug tomorrow at 10:00

Слакбот подтверждает установку напоминалки из консоли

Слакбот понимает все формулировки даты напоминания, которые я пробовал — in 1 hour, at 12:00, on Tuesday, next week, mar 28, every day at 4:20pm. На русском не понимает, но это не страшно.

Типичные сценарии использования:

  • Ставлю себе напоминалку на завтра о чужом сообщении, если кто-то из американской части команды просит меня что-то сделать, когда у меня уже кончился рабочий день.
  • Ставлю себе напоминалку на 1 час о чужом сообщении, если всплыла какая-то задача, а я сейчас занят чем-то другим и не хочу переключаться.
  • Ставлю себе напоминалку на завтра о своем сообщении, если писал кому-то из удаленной команды и хочу завтра пингануть его еще раз, если за ночь мне не ответят.
  • Ставлю себе консольную напоминалку на шесть часов вечера, чтобы обсудить какие-то вопросы с американскими коллегами, когда у них уже будет утро.
  • Ставлю себе консольные напоминалки вообще обо всём подряд.
  • Ставим напоминалку на канал о праздниках удаленной команды, чтобы заранее решить все вопросы, пока они еще на работе.

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

По функциональности это обычный туду-лист. Но оверхед у встроенных напоминалок гораздо ниже. Не нужно открывать отдельное приложение. Не нужно писать описание задачи. Сроки напоминания подбираются автоматически и довольно разумно.

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

Нет комментариев
← Раньше