Кроссворд из регулярных выражений: интерактивная версия

в 9:36, , рубрики: css3 transform, html, javascript, кроссворд, ненормальное программирование, Регулярные выражения, метки: , , , ,

Вдохновлённый недавним постом и комментарием к нему, решил сделать аналогичную интерактивную версию.
Есть навигация с клавиатуры, подсветка активных строк, а также индикация соответствия строки регулярному выражению. Для удобства подсказки выделенной ячейки поворачиваются горизонтально.
Разметка – чистый HTML+CSS3.
Почти работает в последних версиях популярных браузеров. В IE9 глючит навигация мышкой, в FF и Opera наблюдаются проблемы с производительностью. И только Chrome – 100% OK.
Буду благодарен за советы по оптимизации.
Ссылка – вот. Детали реализации – под катом.
image

Реализация

Пожалуй, самое интересное в реализации – это сетка кроссворда. Ячейка сверстана с помощью развития идеи «честных полигонов». Если коротко – создаются несколько контейнеров с visibility:hidden и overflow:hidden, что предоставляет отсекание лишнего содержимого. Внутри создаётся содержимое с visibility:visible. Использование этого вместе с вращением у контейнеров позволяет задать конечному элементу форму практически любого выпуклого многоугольника.
Чтобы сделать этот многоугольник с границами в несколько пикселей, к содержимому были добавлены дополнительные внешние контейнеры с аналогичными поворотами и нужными границами. Суть показана на картинке. Здесь красным пунктиром обозначены внешние «невидимые контейнеры», чёрным – внутренние контейнеры с границами.
Кроссворд из регулярных выражений: интерактивная версия
Сначала идут 3 вложенных друг в друга элемента с красной рамкой, внутри них – так же вложенные видимые контейнеры с чёрной рамкой.

Код
HTML

<span class="hexcell">
	<span>
		<span>
			<span>
				<span>
					<span class="input"></span>
				</span>
			</span>
		</span>
	</span>
</span>

CSS

.hexcell {
	display: inline-block;
	vertical-align: middle;
	text-align: center;
	width: 50px;
	height: 70px;
	overflow:hidden;
	visibility:hidden;
	-webkit-transform: rotate(120deg);
	   -moz-transform: rotate(120deg);
	    -ms-transform: rotate(120deg);
	     -o-transform: rotate(120deg);
	        transform: rotate(120deg);
}
.hexcell span {
	position:relative;
	width:100%;
	height:100%;
	display:inline-block;
	overflow:hidden;
	visibility:hidden;
	vertical-align: middle;
	text-align: center;
}
.hexcell > span {
	-webkit-transform: rotate(-60deg);
	   -moz-transform: rotate(-60deg);
	    -ms-transform: rotate(-60deg);
	     -o-transform: rotate(-60deg);
	        transform: rotate(-60deg);
}
.hexcell > span > span {
	-webkit-transform: rotate(-60deg);
	   -moz-transform: rotate(-60deg);
	    -ms-transform: rotate(-60deg);
	     -o-transform: rotate(-60deg);
	        transform: rotate(-60deg);
}
.hexcell > span > span > span{	/*первая рамка*/
	border: 1px solid #000000;
	height:68px;
	width:48px;
	visibility:visible;
	-webkit-transform: rotate(120deg);
	   -moz-transform: rotate(120deg);
	    -ms-transform: rotate(120deg);
	     -o-transform: rotate(120deg);
	        transform: rotate(120deg);
}
.hexcell > span > span > span > span{	/*вторая рамка*/
	border: 1px solid #000000;
	height:68px;
	width:48px;
	top:-1px;
	left:-1px;
	visibility:visible;
	-webkit-transform: rotate(-60deg);
	   -moz-transform: rotate(-60deg);
	    -ms-transform: rotate(-60deg);
	     -o-transform: rotate(-60deg);
	        transform: rotate(-60deg);
}
.hexcell > span > span > span > span > span.input{	/*содержимое с третьей рамкой*/
	border: 1px solid #000000;
	height:68px;
	width:48px;
	top:-1px;
	left:-1px;
	position:relative;
	visibility:visible;
	font-size:34px;
	-webkit-transform: rotate(-60deg);
	   -moz-transform: rotate(-60deg);
	    -ms-transform: rotate(-60deg);
	     -o-transform: rotate(-60deg);
	        transform: rotate(-60deg);
}

Для корректного объединения ячеек в сетку делается следующее:

  • ячейки оборачиваются в контейнер, содержимое которого выравнивается по центру
  • используется псевдо-border-collapse: всем ячейкам, кроме последней, ставится меньшая ширина и последнего элемента (контейнер содержимого) убирается правая граница
  • для совмещения строчек добавляется отрицательный margin-top

В такой комбинации несколько поставленных рядом ячеек с нужными стилями выстраиваются в нормальную сетку.
Для расстановки заголовков средствами CSS они добавляются перед соответствующей ячейкой в контейнер с абсолютной позицией и выравниванием по правому краю. Таким образом, пропадает привязка к размеру строки и достаточно правильно расположить контейнер через CSS transform.
Всё остальное не представляет из себя ничего сверхъестественного, потому не буду это описывать в посте. Желающие смогут всё найти в исходниках.

Работоспособность

Отдельные вопросы вызывает функционирование. Кроссворд гарантированно функционирует только под Webkit (разработка велась под Chrome последней версии). В Firefox и Opera тоже работает, но почему-то с заметными тормозами, особенно в Opera. Как показал профайлер в той же Opera, больше всего времени уходит на перерисовку, даже с отключёнными transitions. Под IE10 не тестировалось. Под 9-м был баг с позиционированием заголовков (горизонтальные съезжали влево). Как я понял, это какая-то его специфика. Первый элемент в строке с position:absolute съезжает к левому краю, несмотря на отсутствие явного указания положения. Исправлено через display:inline-block у контейнера строки.
Также вместе с поворотами криво рендерится текст. В целом, как показал опыт, рендеринг графики вместе с transform пока оставляет желать лучшего.

Автор: UZER2006

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js