28.05.2009
Динамический ссылки — никакие не ссылки!
Сделал потрясающее открытие для себя.
Как известно, есть обычные ссылки, а есть «динамические» — т. е. такие, по клику на которые браузер не переходит на другую страницу (прямо или «как бы»), а выполняет какие-то действия, javascript-код, например. Как бы это не кнопка получается (кнопки больше для отправки форм используются, конкретных функциональных действий). Но и не совсем ссылка. Вот, к примеру, целая связка таких ссылок в админке Wordpress («Изменить», «Помощь»):
Большинство веб-мастеров оформляет такие ссылки через тег A с параметром href. В результате при наведении на такую «ссылку» она отображается в строке состояния браузера. И хорошо, если по человечески, например «http://www.perfectomania.com/wp-admin/post-new.php#edit_timestamp». Часто просто «http://www.perfectomania.com/wp-admin/post-new.php#» выходит (когда мы находимся на http://www.perfectomania.com/wp-admin/post-new.php) — т. е. значит, что в href прописали «#». Бывает вообще «javascript:» вылазит.
Чтобы этот дурацкий статус не появляся, когда он не нужен, я попробовал убрать href вообще. Помогло, но валидатор предсказуемо плюнулся. И тут меня осенило — а нафиг вообще прописывать такие вещи через тег А? Достаточно сделать SPAN, а в CSS прописать все нужные параметры. Получится валидно, семантично и юзабильно.
У Лебедева это понимают («веб-страницу»), а в Гугле и вообще в большинстве мест — нет («swap»).

Я называю такие ссылки «функциональными», хотя мне кажется, что это не самое лучшее название. И я считаю, что если у вас unobtrusive javascript — ссылка должна быть сделана тегом «a» вместе с атрибутом «href». У Лебедева на упомянутой сранице сделано плохо с точки зрения юзабилити. Почему я не могу открыть ссылку «веб-страницу» в новом табе миддл-кликом? В данном случае ссылка могла бы выглядеть как «/tools/orfograf/#webpage» или «/tools/orfograf/webpage».
1mdm, если может понадобиться открыть в новом окне — да, можно через А. Я же не говорю, что у него там юзабильно, просто видно что технолог в курсе проблемы :)
Их прописывают через A, чтобы они работали при отключенном яваскрипте. Но если такая функциональность не реализована, тогда да, А тут лишний.
Михаил, в большинстве случаев совместимость с отключенными скриптами тут не при чем. Просто вот не пробило людей еще, как меня сегодня, что А тут не аксиома :)
На самом деле надо делать через a href основную массу. Через span и т.п. делать только кнопки типа «сохранить» или ещё чего. Т.е. то что строго индивидуально.
А в href указывать какая страница должна подгрузиться через якоря. То есть, например, пользователь что-то нажал и у него открылось или подгрузилось по принципу ajax окошко для регистрации и он захотел дать эту ссылку приятелю, и если приятель перейдёт по ссылке и у него включен javascript, то страница загрузится также как у того, кто дал ссылку. Span, конечно, избавит от проблем того что ссылки не ссылки. Но это всё-таки не совсем правильный подход. (про это написано несктолько топиков тут, например)
Krov, если определенное положение дел на странице захотят добавлять в закладки или посылать друзьям — да, правильно через А. Я не спорю. Хватает примеров, когда это невозможно — а все равно делают через А. Вот я дал ссылку на Google, где это как раз вообще не нужно.
Кстати, я вот на kasko.maanimo.com сделал функциональные ссылки как раз с помощью span-ов. Хотя если задуматься, то можно было и через «a» реализовать, чтобы и в новом табе открывалось, и без JS работало.
Ссылки и кнопки в отличие от спанов имеют фокус.
Фокус настраивается CSS.
Я не о :focus.
Разве можно по спанах перемещаться табами и клавиатурой вообще?
См. кстати:
http://www.slideshare.net/MournerV/javascript-web-1439514
Волошин Сергей, это да, важно.
tabindex можно применять к span. Это будет не валидно в рамках HTML, но это поддерживается… кажется в HTML 5 это уже включено.
Span, Tab, tabindex, HTML 5, etc.
Посмотрел как реализована поддержка «хождения табом» в трех браузерах, которые установлены у меня на Маке:
Safari
Tab ходит только по контролам форм, причем, в соответствии с system-wide настройкой перехода по нажатию клавиши Tab в Mac OS X — «Text boxes and lists only»/«All controls». При изменении настройки ОС, Safari меняет поведение «на лету».
Ходить табом по ссылкам на странице ТОЖЕ МОЖНО, для этого нужно удерживать клавишу Alt (забавная комбинация клавиш — Alt+Tab, интересно, как они реализовали возможность хождения по ссылкам в Safari/Windows).
Атрибут tabindex на элементе span в Safari не работает.
У интерфейса самого браузера есть одна неприятная особенность, которая проявляется при включении в Mac OS X опции перехода табом по всем контролам: Tab ходит по каждой(!) видимой закладке/вкладке в панели закладок и панели вкладок соответственно (зачем?! Логичнее было бы для этого использовать курсорные стрелки). Если активна адресная строка браузера, в определенных ситуациях «табать» до контента страницы приходится очень долго.
FireFox
System-wide настройка перехода по клавише Tab в Mac OS X отражается на поведении Firefox-а так:
— «Text boxes and lists only» — Tab ходит по текстовым полям форм и по некоторым(!) элементам с указанным атрибутом tabindex (например, элемент span — да, а checkbox в форме — нет :-), списки игнорируются (вполне вероятно, что Firefox отображает списки контролами, которые Mac OS X не считает списками).
— «All controls» — Tab ходит по всем контролам форм, по элементам с указанным атрибутом tabindex и по каждой ссылке.
После изменения этой настройки ОС, Firefox следует перезагрузить, чтобы он изменил свое поведение.
Несмотря на то, что атрибут tabindex на элементах span работает, заставить сработать onclick с клавиатуры нельзя, хотя, как я понял, в драфте HTML 5 говорят, что click срабатывать должен:
(http://www.w3.org/TR/html5/editing.html#specially-focusable).
Opera
System-wide настройка перехода по клавише Tab в Mac OS X игнорируется на территории Норвегии :-)
Tab ходит только по контролам форм и элементам с указанным атрибутом tabindex. По ссылкам не «потабаешь».
Событие click на активном элементе span срабатывает при нажатии на клавишу Enter.
Словом, по-моему, ближе всех к комфортному «табанью» подошли разработчики Safari (если закрыть глаза на панель закладок и панель вкладок): по умолчанию переходы осуществляются по контролам форм в соответствии с настройкой ОС, а при удержании Alt, ходить можно и по ссылкам. Однако, атрибут tabindex на элементах span в Safari не поддерживается, но, в принципе, это же HTML 5 Draft как-никак.
Идея со элементом span вместо якоря (там где последний не к месту) хороша, но с задачей доступа к такому элементу с клавиатуры, среди вышеуказанных браузеров на платформе Mac OS X, справляется только (бугога) Opera.
Алексей, прикол в том, что чтобы считать задачу решенной (для пользователей, которым так нужен этот tabindex — достаточно, чтобы тот браузер которым ОНИ пользуются поддерживал его. Мы сейчас вообще о ком говорим? О слепых и слабо видящих? Людей с нарушением моторики? Так нужно смотреть то, чем они пользуются, а не самые популярные браузеры.
Я бы посмотрел на вопрос в таком разрезе: есть у HTML некая семантика. Да, да, я знаю, что устаревшая, и не отражающая идею «функциональных ссылок», да и многих других современных концепций, но тем не менее – есть.
Это – в самой природе HTML, и, следовательно, всех, кто с ним работает, например – браузеров или поисковых машин, или любых автоматических обработчиков. Они опираются на эту модель, и они исходят из предположения, что правила игры соблюдаются.
Приведенный пример с tabindex это хорошо иллюстрирует: с точки зрения разработчика браузера, табом есть смысл ходить только по тому, по чему можно кликнуть, или заполнить. Теоретически, можно ходить по всему вообще – может, абзац текста скопипейстить – тоже нужная вещь, и тогда хождение по абзацам с выделением это тоже нужная для таба вещь. Но пришлось выбирать, и я понимаю их выбор.
Все элементы HTML наделены семантикой, и по ней можно с большой вероятностью сказать, какой элемент пассивный, а какой-активный. Например, все элементы форм и ссылки – активные. Потому что с ними можно что-то такое делать – кликать, например.
Остальные элементы служат для пассивной задачи – отобразить контент. Поэтому таб будет переключать фокус только по активным элементам, и на мой взгляд, это совершенно правильно.
Я не понимаю, почему разработчик должен игнорировать этот факт, и использовать для активных элементов семантически-пассивные тэги. Единственным аргументом, который я могу понять – невозможность сделать задуманное в рамках этого тэга. Но и это – движение против семантики, но хоть понятно, ради чего.
А ради чего делать такие ссылки span-ом? Span – обертка, выход из мира HTML, построение своего уникального мира. Это дифференциация, а не интеграция. Зачем?
В пользу ссылки я скажу, что грамотно оформленная такая вот «функциональная ссылка» изменит якорь страницы, и зафиксирует, таким образом, состояние этого элемента управления. Теперь все прелести интернета, связанные со ссылками – ура! – работают. Ее можно положить в закладки. К ней можно вернуться. Ее можно послать по аське. С ней можно делать все, что можно делать со ссылками, и это прекрасно!
А что же span? Только и радости – что в статус-баре не будет показываться строка?
Sniff, а если ссылки, к примеру, в контрольной панели сложного сервиса, где куча динамики? Таким сервисом гарантированно не будут пользоваться инвалиды и ссылок на динамические изменения не будут давать другу. Вот здесь строка состояния — враг, она только мешает. Да и span выйдет семантичнее ссылки в этом случае. «Открыть в новом окне» тут — совершенно неадекватная опция по клику правой кнопкой мышки.
От моего ответа же ничего не изменится, правда? Каждый разработчик волен выбрать свой путь решения, и эта свобода прекрасна.
Говорят, каждый PHP-программист должен написать свою гостевую книгу, свой шаблонизатор и свою CMSку. И ведь действительно, это очень хорошие упражнения, они развивают ум и владение инструментом. К счастью, почти все PHP-программисты, прошедшие через эти этапы, скоро выясняют, что это только упражнения, нет на самом деле никакого практического смысла действительно делать свой шаблонизатор или свою CMS-ку. Их уже сделано огромное количество, и среди них есть очень, очень хорошие, почти всегда лучше, чем свои, решения. Это не обязательно делать всем программистам (Да, есть исключения, так появляются новые шаблонизаторы и CMSки, и это тоже прекрасно!).
Я вижу два варианта решения, назовем их условно «спаны» и «ссылки».
Чем хороши спаны? Тем, что в статусбаре не будет видно ссылки. Хорошо ли это? Ну, наверное, неплохо. А что, есть такая проблема, что люди теряются от этих ссылок? Нет, пожалуй, такой проблемы нет: эти ссылки появляются там постоянно, десять раз в минуту, просто от перемещения мышки. Кто-то всерьез считает, что это раздражает пользователей? Я, наверное, не очень много юзертестов проводил, но ни разу такой проблемы не увидел. И очень удивлюсь, если кто-то увидел.
Таким образом, это решение несколько надуманной проблемы. Это не хорошо, это именно что неплохо. Никому же не будет хуже, если там не будет ничего мелькать? Нет, никому. Лучше – тоже, очень сомневаюсь. Но хуже – наверное нет.
Чем хороши ссылки? Тем, что это ссылки! Это старые добрые ссылки, они работают как любые другие ссылки, а уж со ссылками много чего люди научились делать за годы интернета. Это приведение к общему знаменателю, это сведение задачи к уже решенной. Это понятно и просто.
Это решение, интегрирующее твой проект в мир, в котором живет пользователь. В мир ссылок и кнопок. В мир понятных и привычных концепций. Я думаю, это прекрасно, даже если это мегазакрытая суперадминка, которую все равно увидит всего один человек.
Sniff, я согласен, что в 90% случаев ссылка лучше спана. Оставляю за собой право в 10% использовать спаны :)
А по поводу юзер-тестов… «Если бы разработчики всегда опирались на мнение фокус-групп — у нас бы сейчас была чертовски удобная дубина для охоты на мамонтов»
Не ожидал, что ты не понимаешь разницы между юзер-тестами и фокус-группами.
Onclick вешать на ссылку желательно только тогда, когда ее можно в обход этого события открыть в новом окне. Если нельзя — button.
Sniff, в смысле цитаты разницы действительно не вижу. Поясни.
Разница в том, за чем ты идешь и что ты получаешь.
Если ты идешь за задачами, спросить – «что же мне делать, чтобы вам понравилось?» – то ты идешь к фокус-группе за идеями. Они посоветуют тебе, чтобы дубина была удобнее, чтобы тут была еще одна ручка, вес скорретировать.
Если ты идешь за подтверждением гипотез, спросить – «ну как вам решать свою проблему с вот таким вот инструментом, который я тут сделал?» – ты проводишь юзертест, и узнаешь, что автомат калашникова не очень удобен, потому что стреляет только 30 раз, а дубиной можно бить вечно, что он неудобен, потому что надо целится точно, потому что патроны дорогие.
Фокус-группы они как бы для выявления потребностей, юзер-тесты – для проверки решений.
Называться могут по-разному (юзер-тесты тоже могут проходить на фокус-группе по сути), но в контексте твоей цитаты речь именно о фокус-группах для выяснения потребностей.
Разница в том, какую задачу ты решаешь с помощью этих людей.
Sniff, дело в том, что я понимаю цитату шире. Даже если новое решение неудобно пользователям на момент внедрения — это не значит, что его не следует внедрять. Это просто информация для размышления, а не аксиома.
Ну я ж сразу сказал – мой ответ ничего не изменит, и это прекрасно. Делай, как считаешь нужным.
Интересный факт: слепые, слабовидящие и люди с нарушением моторики используют популярные браузеры, потому что хотят делать вещи, которые делают люди без подобных ограничений. Нету ИЕ для глухих, нету Оперы для дальтоников. Есть accessibility средства ОС, остальное от сатаны.
А говорим мы сейчас о перфекционизме в юзабилити.
P. S.: Отдельно приятно отметить что вы, Роман, относите людей, которые любят использоватьклавиатурный доступ к группе инвалидов. :-)
Алексей, дело в том, что некоторые интерфейсы просто нецелесообразно адаптировать для не «идеального» пользователя. Не потому, что сложно, а потому, что такой пользователь ими просто не воспользуется в полной мере. Вы представляете себе человека с плохим зрением, копающегось в таблицах Гугл Аналитика?
А клавиатурный доступ, извиняюсь, как можно использовать нормально, если к нужному элементу 20 раз может потребоваться протабить?
Про button идея отличная, но разве он не обязан быть внутри form?
У меня логика такая:
Я различаю обычную классическую ссылку и псевдоссылку.
1. Если клик приводит к переходу на другую страницу — то это однозначно ссылка и у нее должны быть все атрибуты присущие ссылке (хреф, фокус, ховер, визитед…)
2. Если клик приводит к динамическому изменению контента, без перезагрузки страницы, — то это псевдоссылка. И тут возможны варианты ее реализации:
— классическая ссылка, клик по которой вызывает динамическу загрузку контента с указанного адреса. В этом случае хреф нужен обязательно, например, что бы поисковики могли пройти по ссылке и прочитать контент.
— элемент, клик по которому вызывает модификацию контента на текущей странице. Например, различные переключалки (нажали — чтото скрылось, а чтото открылось), различные удобности заполнения форм («выделить всё», «скрыть», «очистить»). Это может быть стандартная кнопка (button или input_type=button) или инлайновый (span, i, b, em, strong) или блоковый элемент, но только не классическая ссылка с хрефом (т.к. хреф тут не имеет смысла). В случае, если мы имеем дело с инлайновым текстовым элементом, что бы он НЕ выглядел как ссылка, я декорирую его штрихпунктиром (обязательно!).
Использование в хрефе псевдоссылок javascript:bla-bla-bla или просто пустой хреф — СТАРПЕРСТВО.
Максим, все правильно сказал.
Отличная статья, спасибо) Как раз искал решение, как бы избавится от показываемого кода js в статусной строке. Решение поражает своей элементарностью)
Кстати, вот Степа, очень популярно раскрывает тему ссылок:
http://www.artlebedev.ru/tools/technogrette/html/links/
Я, конечно, с ответом задержался, но мысль свою я хочу закончить :-)
Там, где есть техническая возможность адаптации интерфейса для инвалидов, она должна быть реализована. Вижу только два потенциально сдерживающих фактора: незнание (вообще-то usability берет в расчет accessibility, и, если человек профессионально занимается первым, то не знать о существовании второго он не может) и недостаточное количество ресурсов («У нас тут релиз завтра, мы и так задержались на месяц, а вы про каких-то инвалидов!» — это касается, в основном, бизнеса).
Кстати, в Гугл аналитикс все прекрасно масштабируется — плохо видящие счастливы.
Легко и просто! Ясно, что «табать» до первого контрола никто не будет, когда на столе лежит мышка, но как только активирован первый элемент формы, гораздо удобнее дальше заняться именно «табаньем». Вот к примеру, есть форма:
Имя: ______________Фамилия: ______________
Email: ______________
Если хотите, Вы можете заполнить дополнительные поля.
[ Отправить ]
«Показать дополнительные поля» здесь та самая «динамическая ссылка». Я хочу, заполнив поле «Email» нажать Tab, активировать дополнительные поля (к примеру нажатием клавиши «Enter»), которые раскроются ниже, снова нажать и продолжить заполнять форму, не прикасаясь к мышке.
Имя: ______________
Фамилия: ______________
Email: ______________
Дополнительные поля, расположенные ниже, необязательны для заполнения.
Вы можете их
Адрес: ______________
Телефон: ______________
[ Отправить ]
Я не призываю использовать везде анкоры — боже упаси!, я просто хотел показать, что в большинстве современных браузеров для любимой платформы использование span+onclick имеет по крайней мере один достаточно серьезный минус, и поэтому фраза «Получится валидно, семантично и юзабильно» несколько лукавит в своем последнем наречии. :-)
Ох, все что между угловыми скобками робот обкусал…
Вот корректный кусок:
Имя: ______________Фамилия: ______________
Email: ______________
Если хотите, Вы можете заполнить дополнительные поля.
_Показать дополнительные поля_
[ Отправить ]
«Показать дополнительные поля» здесь на самая «динамическая ссылка». Я хочу, заполнив поле «Email» нажать Tab, активировать дополнительные поля (к примеру нажатием клавиши «Enter»), которые раскроются ниже, снова нажать Tab и продолжить заполнять форму, не прикасаясь к мышке.
Имя: ______________
Фамилия: ______________
Email: ______________
Дополнительные поля, расположенные ниже, необязательны для заполнения.
Вы можете их _скрыть_
Адрес: ______________
Телефон: ______________
[ Отправить ]
Робот съел текст в треугольных скобках.
Errata:
Имя: ______________Фамилия: ______________
Email: ______________
Если хотите, Вы можете заполнить дополнительные поля.
_Показать дополнительные поля_
[ Отправить ]
«Показать дополнительные поля» здесь на самая «динамическая ссылка». Я хочу, заполнив поле «Email» нажать Tab, активировать дополнительные поля (к примеру нажатием клавиши «Enter»), которые раскроются ниже, снова нажать Tab и продолжить заполнять форму, не прикасаясь к мышке.
Имя: ______________
Фамилия: ______________
Email: ______________
Дополнительные поля, расположенные ниже, необязательны для заполнения.
Вы можете их _скрыть_
Адрес: ______________
Телефон: ______________
[ Отправить ]
К сожалению, робот «съел» куски текста в треугольных скобках, но исправление я отправить почему-то не могу :-(
Три последних сообщения, включая это, можно стереть. :-)