Материалом о разработке калькулятора на CSS и HTML, без файла JS, тега script и обработчиков событий в HTML делимся к старту курса по Fullstack-разработке на Python. За подробностями приглашаем под кат.
Постановка задачи
В проектах CSS часто в обычные статические HTML и CSS компилируются HAML и SCSS. Последние при этом применяются во многих сумасшедших проектах, но свой я решил не усложнять: взгляните на весь код.
Как это сделать?
Начнём со взаимодействия с пользователем. Как без JS понять, что кнопка нажата? Ответ: при помощи значений радиокнопок:
<input type="radio" name="x" id="q-1" /> <input type="radio" name="x" id="q-2" /> <label for="q-1">Quote 1</label> <label for="q-2">Quote 2</label> <p class="quote-1">...</p> <p class="quote-2">...</p>
и
input, p { display: none } #q-1:checked ~ .quote-1 { display: block; } #q-2:checked ~ .quote-2 { display: block; }
дают результат:
Метки (label) соединены с input так, что нажатие на них станет нажатием на input. Метки упрощают стиль, поэтому они лучше нажатия на радиокнопку напрямую.
Символ ~ — это селектор, выбирающий элементы на том же уровне сложности: A ~ B соответствует элементам B после A. Код выше по умолчанию скрывает элементы p, отображая их, только когда подключенная радиокнопка выбрана.
Переменные и счётчики CSS
Значения счётчиков в функции calc неприменимы, поэтому, чтобы сгенерировать число, объявим переменную. Напишем имя свойства с двумя дефисами (—) в начале и любым значением CSS: —colour: brown или —digit: 3. Для подстановки переменной вызовите функцию CSS var.
Счётчики CSS хранят и отображают числа. Они применяются, например, для автоматической нумерации разделов.
<input type="radio" name="theFirstDigit" id="set-to-1" /> <input type="radio" name="theFirstDigit" id="set-to-2" /> <input type="radio" name="theFirstDigit" id="set-to-3" /> <!-- insert labels --> <div class="number-dsplay"></div>
и
#set-to-1:checked ~ div { --digit: 1; } #set-to-2:checked ~ div { --digit: 2; } #set-to-3:checked ~ div { --digit: 3; } .number-display { counter-increment: digit var(--digit); } .number-display::after { content: counter(digit) }
дают результат:
Когда пользователь отмечает кнопку, внутри div задаётся значение переменной —digit, наследуемое всеми дочерними элементами. Это значение нельзя вывести напрямую, поэтому увеличим счётчик digit и отобразим его через сгенерированный content.
Чтобы получить числа больше 9, нужно просто продублировать уже существующие цифры. За счёт тщательно продуманной структуры HTML и использования промежуточных переменных дублирование CSS сводится к минимуму:
!-- digit inputs name="theFirstDigit --> <div class="first-digit"> <!-- digit inputs name="theSecondDigit" --> <div class="second-digit"> <!-- ..and so on --> </div> </div>
/* Include previous CSS */ .first-digit { --first-digit: var(--digit); } .second-digit { --second-digit: var(--digit); }
Переменная —digit по-прежнему задаётся через input, каждый отдельный div принимает это значение и присваивает его —first-digit, —second-digit и так далее: повторять код #set-to-1:checked для каждой цифры не нужно.
Функция CSS calc
Функция calc в CSS выполняет вычисления и применяется, например когда задаётся значение width (ширины): calc(100% — 95px). Определим с помощью calc число элемента input, а также результат всех вычислений:
[name="theFirstDigit"]:checked ~ * .set-number { --number: var(--first-digit); } [name="theSecondDigit"]:checked ~ * .set-number { --number: calc(var(--first-digit)*10 + var(--second-digit)); } [name="theThirdDigit"]:checked ~ * .set-number { --number: calc(var(--first-digit)*100 + var(--second-digit)*10 + var(--third-digit)); } /* and so on */
Селектор * выбирает все элементы, поэтому в коде выше вы найдёте .set-number — потомка любого элемента после input с флажком и определённым именем. Второй селектор переопределяет первый просто потому, что расположен после первого.
Добавив несколько input для выбора операции, аналогичным методом мы получим окончательный ответ. В этом случае значения просто захватываются в счётчике и отображаются. Свойство content тоже может принимать строку, отображая операцию калькулятора.
@property и @counter-style
Теперь можно создать калькулятор. Но вот загвоздка: в счётчиках есть только целые числа, знаков после запятой у нас нет, поэтому нужно разделить число на целую и дробную части и найти способ округления чисел.
Счётчики при этом использовать нельзя, ведь их нельзя завести в calc. Воспользуемся экспериментальной функцией @property: она определяет переменную с помощью такого функционала, как проверка типа или контроль за наследованием значений. Определим @property:
@property --integer { syntax: '<integer>'; initial-value: 0; inherits: true; }
Так любое присваиваемое —integer значение округляется до целого числа. Чтобы отобразить число с точностью до семи знаков после запятой, сначала выполним следующие вычисления. Здесь —number определяется внешним кодом:
.number-display { --abs-number: max(var(--number), -1 * var(--number)); /* By suptracting 0.5 we make sure that we round down */ --integer: calc(var(--abs-number) - 0.5); --decimal: calc((var(--integer) - var(--abs-number)) * 10000000); --sign-number: calc(var( --abs-number) / var(--number)); }
Используя —integer для целых чисел и —decimal для знаков после запятой, можно увеличивать счётчики с похожими именами, но отображать их напрямую нельзя: например, для числа 1,005 значение —integer равно 1, а значение —decimal — 5.
Знаки после запятой дополняются пользовательским свойством @counter-style, оно применяется для отображения знака «минус»: мы не можем сообщить системе, что число -0,5 — это «отрицательный нуль». Вот как правильно отобразить -0,5:
@counter-style pad-7 { system: numeric; symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9"; pad: 7 "0" } @counter-style sign { system: numeric; symbols: "" ""; } .number-display::after { content: counter(sign-number, sign) counter(integer) "." counter(decimal, pad-7); }
Второй аргумент функции counter — это стиль. В стиле pad-7 определяется обычная система счисления, за исключением того, что любое значение с менее чем семью цифрами дополняется нулями.
В стиле sign тоже используется числовая система, но мы определили символы пустыми, поэтому отображается в нём только знак «минус», если нужно.
Возможности
Всё это — ключевые элементы калькулятора, но осталось ещё кое-что — это стилизация. Вы могли заметить, что для каждой цифры числа в текущей конфигурации есть отдельный набор из нескольких input.
Чтобы всегда показывать метку следующей цифры, можно применять селектор ~, :checked и свойство display, а content — разбить на отдельные элементы, таким образом показывая десятичную часть только при необходимости.
Теоретически через генерацию HTML можно приблизиться к научному калькулятору. Например, можно воспользоваться симметрией и периодичностью тригонометрических функций, применив приближённые вычисления.
Самое сложное — скобки, ведь неизвестно, как динамически добавить их в calc, поэтому для каждого сценария пришлось бы иметь отдельные селекторы и CSS.
Заключение
Я написал этот калькулятор просто ради забавы, но многому научился, это было очень весело, поэтому если у вас есть идея пустякового проекта, реализуйте её. Почему нет?
А пока вы практикуетесь, мы поможем прокачать ваши навыки или с самого начала освоить профессию, востребованную в любое время:
Выбрать другую востребованную профессию.
Краткий каталог курсов и профессий
Data Science и Machine Learning
Python, веб-разработка
Мобильная разработка
Java и C#
От основ — в глубину
А также
ссылка на оригинал статьи https://habr.com/ru/company/skillfactory/blog/661343/
Добавить комментарий