Личный и рабочий блог Николая Огрызкова



Развитие сайта

Зачем была создана эта страничка?

Я думаю, всем нам иногда бывает интересно, как тот или иной человек развивался и как начинал путь. Когда объектом интереса стану я, мне бы хотелось, чтобы это было реализовано удобно для всех и с доступностью прямо с сайта.

Именно для этого и создан данный раздел на сайте. Вы можете, во-первых, по дням отследить, как и что я изучал, с самого первого дня развития в формате ленты. Во-вторых, вы можете посмотреть, как в тот или иной день выглядел сайт. На момент создания этой страницы он представлял из себя голый HTML-документ — однако кто знает, каким будет сайт в будущем? =)

Обучение по дням

Дата публикации:

Дни 10—11: ЕГЭ, завершение работы с кнопками и формами и ещё немного лоска с помощью CSS

Так что там с ЕГЭ?

С ЕГЭ всё отлично!

Предмет Количество баллов
Русский язык 61
Математика (профильная) 58
Информатика 20*
* На момент написания статьи официального результата не было; но я сделал только 3 задания, и 20 — это самый лучший расклад. xD

У некоторых может возникнуть справедливый вопрос: и как же это всё отлично, если информатика де-факто не сдана, а по другим двум предметам тоже мало баллов? Дело в том, что я иду в колледж и не иду в вуз. Мне нужен только аттестат, так что я не переживаю. В колледжах не спрашивают баллы ЕГЭ. 😝 Дальше мне нужно будет получить медицинское заключение для колледжа — 3517 ₽, на минуточку! — после чего смогу подавать документы.

Больше кнопок и форм богу кнопок и форм!

Да… возвращаемся к ВОТ ЭТИМ ВОТ. 😩



Какой ваш любимый язык программирования?


Какие у вас любимые домашние питомцы?


Напишите о своём свэге

Бо-о-оже, это было ужасно! Пока запомнишь, как всё это работает, нужно будет это не один раз повторить. Впрочем, никто ничего не запоминает раз и навсегда; в пору интернета всегда есть возможность проверить и уточнить, верно? ;)

Обновление в CSS и немного в доступности

Сегодня я освоил max-width, line-height, padding и ещё некоторую красоту, которая позволила сделать сайт лучше. :> Текст больше не растягивается на всю страницу, а аккуратно располагается в центре; также он стал побольше, а межстрочный интервал приобрёл более удобочитаемый вид. 🌸

По доступности: прогнав свой сайт через Google Lighthouse, я понял, что в моментах, где я даю описание картинок и ссылки на страницы картинок в Pexels, люди со скринридерами получают набор ссылок, которые звучат абсолютно одинаково. (Они слышат что-то вроде «копирайт, [имя сделавших фотографию] на „ссылка: Pexels“». Получается какая-то каша: предлог «на» смешивается со словом «ссылка», а слово Pexels не даёт много информации.) Было придумано изящное и более корректное с точки зрения семантики решение: у тега <a> можно задавать название с помощью aria-label. Теперь человек будет слышать «копирайт, [имя сделавших фотографию]; „ссылка: Часовня тишины на Pexels“». Предлог «на» я убрал от людей без скринридеров, заменив его на длинное тире — выглядит оно даже более профессионально. B)

День 9: кнопки, формы и прочие ужасы, которые за один раз не запомнишь…

Дата публикации:

Кнопки и формы (будь они неладны!)

Всех приветствую! Хотелось бы выйти на режим ежедневных коммитов (мечтать не вредно! 😝), поэтому активно учусь дальше.

Сегодня, после наведения финального лоска в CSS — да, Джеминай мне всё предлагает и предлагает кучу симпатичного, а я всё не против и не против, — я наконец-то возвращаюсь к курсу от FreeCodeCamp по HTML! Следующая тема… о-о-ой, формы и кнопки… Я помню, как я был поражён количеству полученной информации, когда у меня была первая и менее публичная попытка в веб-разработку с курсом уже от BroCode. Надеюсь, в этот раз будет попроще. Хотя длина этого урока на таймлайне не вызывает доверия. 🥲 Попробуем?..

Важное примечание: все формы липовые и мне не приходят на данный момент!

Окей, чат, завтра мне на экзамен последний (конечно, я ничего не знаю и ничего не напишу), так что пойду уже спать. git push origin main и до завтра! 🍓

Дни 5—8: внезапная оптимизация картинок, первые шажки в CSS и ИИ

Дата публикации:

Доведения до ума раздела об истории развития сайта

Что? Да! Я решил, что такой раздел должен быть прямо на сайте с возможностью взглянуть, как всё выглядело в тот или иной день. Вы, вероятно, прямо с неё читаете данный текст. Здесь будут история по дням изучения и история в виде полноценных снапшотов — копий сайта за тот или иной день. Они находятся в самом низу. Внизу этих снапшотов была добавлена подпись о том, что это архивная версия сайта, и кнопки перехода от одного снапшота к следующему и предыдущему — Джеминай мне помог сделать это покрасивее.:>

Желание публиковаться на GitHub

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

Во-первых, надо выбрать лицензию. ИИ предлагает как универсальный вариант лицензию от MIT, но я вспоминаю, что слышал легенды про лицензии GNU и восхищался. Погуглив, я решил, что буду брать AGPLv3. Она хороша тем, что любой человек, который решит работать с моим кодом, будет обязан опубликовать все свои изменения; иначе я буду иметь право его засудить. 🫦 Вот она: свобода кода любой ценой!

Но с такой лицензией я дважды задумался над картинками, которые были у меня на сайте, а именно шуточные скриншоты из GTA в контексте мест, которые мне бы хотелось посетить. Уж не знаю, мог бы я в будущем заинтересовать Rockstar, но, если я правильно понимаю, это одна из компаний с вредными юристами, поэтому я решил не рисковать и брать свободные для распространения фотографии с Pexels. Отлично, с интеллектуальной собственностью — будь оно проклята! — мы разобрались. Теперь можно просто вставить картинки, верно?.. Ну… не совсем.

Оптимизация размера изображений

Итак, загружать оригинал в 2 МиБ — это неприемлемо по нынешним веб-стандартам. Я поговорил об этом с Чатом — ChatGPT, — и тот предложил мне bash-скрипт для сжатия. И после этого я упал в кроличью нору… Я думал расписать подробно, как и насколько разные ИИ мне помогли в создании скрипта, но мне кажется, что это будет излишним. Больше всего мне помогли Джеминай и Клод; первую заготовку сделал Чат, Грок тоже внёс пару правок, но начал слишком быстро просить денег и ограничивая наш чат на 8 часов. Клод выглядел самым способным по коду, хотя Джеминай не отставал (по крайней мере в работе с этим конкретным bash-скриптом) и был разве что подружелюбнее. Но! С Клодом был интересный диалог:

— У меня опять горят глаза насчёт картинок. 🫦 Как это можно реализовать в нашем имеющемся скрипте? 🤔
— Нет. 😄

Серьёзно — сначала напиши хоть одну страницу. Ты не знаешь ещё какие размеры тебе нужны, как картинки будут вписаны в макет, какие брейкпоинты ты выберешь. Дописывать скрипт под размеры которые ты не знаешь — это работа вслепую.

Когда сделаешь первый макет и увидишь что картинка на мобильном занимает 480px, а на десктопе 1200px — вот тогда приходи, добавим за пять минут.

Впервые ИИ мне отказал! Дальше я всё же смог его убедить мне помочь, сказав, что у меня уже есть несколько страниц, но это было интересно. А отказ, если честно, по делу. Как бы то ни было, теперь у меня есть скрипт, который при первом запуске спрашивает, в где хранится директория img, а при втором уточняет, в какую поддиректорию загружать конкретные файлы. Дальше он спрашивает, насколько агрессивную стратегию сжатия использовать; после этого он делает своё дело, сохраняя в директорию /original оригинал изображения, а на директорию выше кидает 7 файлов (каждый меньше 250 КиБ): AVIF и WEBP для экранов смартфонов (640 px), для экранов маленьких ноутбуков и планшетов (1200 px) и для десктопа (1920 px) и JPEG (чтобы в случае чего загрузилось даже на древнейших девайсах), давая в терминале сразу вывод для HTML-файла.

Раз уж такое дело, неудобно будет не разместить прямо здесь эти картинки! (Заодно взгляну, как сделать так, чтобы картинки занимали не пол-экрана.)

Места, которые мне бы хотелось посетить:

  • Хельсинки

    Снежный вид на часовню тишины Камппи в Хельсинки, демонстрирующий современную архитектуру в зимней обстановке
    Хельсинки, Уусимаа, Финляндия
    © Ivan Dražić — Pexels
  • Берлин

    Трамваи на городской улице Берлина с заревом заката, демонстрирующие городскую жизнь и современную архитектуру
    Берлин, Германия
    © Niklas Jeromin — Pexels
  • Акихабара

    Яркая ночь в Акихабаре, Токио, с неоновыми огнями, рекламными щитами и уличной жизнью
    Акихабара, Токио, Япония
    © Şiyar AKBALIK — Pexels

Делюсь не без удовольствия кодом прямо здесь. 💫 (Надеюсь, меня не загрызут люди, которые, не знаю, стояли за созданием bash… кто знает, кто среди читателей будет? Как бы то ни было, это вайб-кодинг — не судите строго. 😝)

Открывайте и используйте на свой страх и риск! 👀
#!/bin/bash
set -euo pipefail

# Определяем, где физически лежит сам скрипт
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_FILE="$SCRIPT_DIR/.img_config"

echo "=== ULTIMATE Image Optimization Script (CLI Parallel Edition) ==="

# ==================== ФУНКЦИЯ НАСТРОЙКИ ПУТИ ====================
setup_base_dir() {
    echo "--- Настройка базовой директории сайта ---"
    echo "Введите абсолютный путь к папке 'img' вашего сайта."
    echo "Пример: /home/micu/Documents/My_site/img/"
    read -r -p "Путь: " user_path

    user_path="${user_path%/}"

    if [ ! -d "$user_path" ]; then
        echo "⚠️ Ошибка: Директория '$user_path' не существует!"
        read -r -p "Всё равно сохранить этот путь? (y/n): " confirm
        if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
            exit 1
        fi
    fi

    echo "$user_path" < "$CONFIG_FILE"
    echo "✓ Базовый путь успешно сохранен в $CONFIG_FILE"
}

# ==================== ОБРАБОТКА ФЛАГОВ (-c / --change-dir) ====================
if [ "${1:-}" = "-c" ] || [ "${1:-}" = "--change-dir" ]; then
    setup_base_dir
    echo "Перезапуск скрипта..."
    exit 0
fi

if [ ! -f "$CONFIG_FILE" ]; then
    echo "Похоже, это первый запуск скрипта!"
    setup_base_dir
fi

BASE_OUT_DIR=$(cat "$CONFIG_FILE")

# ==================== ВЫБОР ПОДДИРЕКТОРИИ (Поста/Дня) ====================
echo ""
echo "Текущий базовый путь: $BASE_OUT_DIR"
echo "Введите название целевой подпапки для картинок (например: day_1):"
read -r -p "Подпапка: " sub_dir

sub_dir="${sub_dir#/}"
sub_dir="${sub_dir%/}"

FINAL_DESTINATION="$BASE_OUT_DIR/$sub_dir"
mkdir -p "$FINAL_DESTINATION"

# ==================== ВЫБОР РЕЖИМА СЖАТИЯ ====================
echo ""
echo "Выберите целевой режим сжатия:"
echo "1) Hero / LCP          — очень строго (<180 KiB)"
echo "2) Content             — строго (<230 KiB)"
echo "3) Banner              — умеренно (<350 KiB)"
echo "4) Gallery             — максимально (<110 KiB)"
read -r -p "Введите номер (1-4): " mode

case $mode in
    1) TARGET_WEBP=184320; MIN_QUALITY=18 ;;
    2) TARGET_WEBP=235520; MIN_QUALITY=22 ;;
    3) TARGET_WEBP=358400; MIN_QUALITY=28 ;;
    4) TARGET_WEBP=112640; MIN_QUALITY=15 ;;
    *) echo "По умолчанию Content"; TARGET_WEBP=235520; MIN_QUALITY=22 ;;
esac

SIZES=(640 1200 1920)
shopt -s nullglob

# Экспортируем переменные, чтобы дочерние процессы их видели
export TARGET_WEBP MIN_QUALITY FINAL_DESTINATION sub_dir SCRIPT_DIR
export -a SIZES

# ==================== ФУНКЦИЯ СЖАТИЯ ОДНОГО РАЗМЕРА ====================
compress_size() {
    local work="$1" local out_webp="$2" local out_avif="$3"
    local target_w="$4" local target_h="$5"

    local avif_target=$(( TARGET_WEBP * 70 / 100 ))
    local current_w=$target_w local current_h=$target_h

    # WebP
    magick "$work" -resize "${target_w}x${target_h}" -quality 72 -define webp:method=6 -define webp:pass=10 "$out_webp"

    # Агрессивный цикл
    for pass in {1..8}; do
        [ -f "$out_webp" ] || break
        local current_size=$(stat -c %s "$out_webp")
        [ "$current_size" -le "$TARGET_WEBP" ] && break

        local quality=$(( 72 - pass * 9 ))
        [ "$quality" -lt "$MIN_QUALITY" ] && quality=$MIN_QUALITY
        current_w=$(( current_w * 90 / 100 ))
        current_h=$(( current_h * 90 / 100 ))

        if [ $(( current_w < current_h ? current_w : current_h )) -lt 320 ]; then
            magick "$work" -resize "${target_w}x${target_h}" -quality "$quality" -define webp:method=6 -define webp:pass=10 -define webp:alpha-quality=30 "$out_webp"
            break
        fi
        magick "$work" -resize "${current_w}x${current_h}" -quality "$quality" -define webp:method=6 -define webp:pass=10 -define webp:alpha-quality=30 "$out_webp"
    done

    # AVIF
    local final_w=$(magick identify -format "%w" "$out_webp" 2</dev/null || echo "$target_w")
    local final_h=$(magick identify -format "%h" "$out_webp" 2</dev/null || echo "$target_h")

    magick "$work" -strip -units PixelsPerInch -density 72 -resize "${final_w}x${final_h}" -quality 60 "$out_avif"
    if [ $(stat -c %s "$out_avif" 2</dev/null || echo 0) -gt "$avif_target" ]; then
        magick "$work" -strip -units PixelsPerInch -density 72 -resize "${final_w}x${final_h}" -quality 40 "$out_avif"
    fi
}
export -f compress_size

# ==================== ВОРКЕР: ОБРАБОТКА ОДНОГО ФАЙЛА ====================
process_single_image() {
    local input="$1"
    [ -e "$input" ] || return 0

    local name=$(basename "$input")
    local base="${name%.*}"
    local ext="${name##*.}"
    local clean_ext=$(echo "$ext" | tr '[:upper:]' '[:lower:]')
    [ "$clean_ext" == "jpeg" ] && clean_ext="jpg"

    local img_dir="$FINAL_DESTINATION/$base"
    local img_originals_dir="$img_dir/original"
    mkdir -p "$img_originals_dir"

    # Создаем ИЗОЛИРОВАННУЮ временную папку для конкретно этого файла
    local tmp_work_dir=$(mktemp -d "$SCRIPT_DIR/.tmp_work_${base}_XXXXXX")
    local work="$tmp_work_dir/${base}_work.${ext}"

    # Перенаправляем вывод всего процесса в переменную, чтобы логи не перемешивались в кашу
    local log_output=""

    log_output+="\n=== Processing: $name ===\n"
    log_output+=" → Результаты полетели в: $img_dir\n"

    cp "$input" "$img_originals_dir/$name"
    cp "$input" "$work"

    local has_alpha=0
    if [[ "$clean_ext" == "png" ]]; then
        if magick identify -format "%[channels]" "$work" 2</dev/null | grep -q 'a'; then
            has_alpha=1
        fi
    fi

    if [ "$has_alpha" -eq 1 ]; then
        log_output+=" → Alpha PNG — предварительное сжатие...\n"
        pngquant --quality=40-85 --speed=1 --force --output "${work%.png}_tmp.png" "$work" && mv "${work%.png}_tmp.png" "$work" || true
        oxipng -o 6 --strip safe --quiet "$work" || true
    fi

    local src_w=$(magick identify -format "%w" "$work" 2</dev/null || echo 0)
    local src_h=$(magick identify -format "%h" "$work" 2</dev/null || echo 0)

    local max_created_w=0
    local max_created_h=0

    for size in "${SIZES[@]}"; do
        if [ "$size" -gt "$src_w" ] && [ "$size" -gt "$src_h" ]; then continue; fi

        if [ "$src_w" -ge "$src_h" ]; then
            local target_w=$size; local target_h=$(( src_h * size / src_w ))
        else
            local target_h=$size; local target_w=$(( src_w * size / src_h ))
        fi

        local out_webp="$img_dir/${base}-${size}.webp"
        local out_avif="$img_dir/${base}-${size}.avif"

        compress_size "$work" "$out_webp" "$out_avif" "$target_w" "$target_h"

        local final_w=$(magick identify -format "%w" "$out_webp" 2</dev/null || echo "$target_w")
        local final_h=$(magick identify -format "%h" "$out_webp" 2</dev/null || echo "$target_h")
        log_output+="      ✓ [${size}px] Созданы варианты WebP и AVIF [${final_w}x${final_h}]\n"

        max_created_w=$final_w
        max_created_h=$final_h
    done

    # Умный расчет размера фолбэка (Дубли удалены!)
    local fallback_w=$max_created_w
    local fallback_h=$max_created_h

    if [ "$max_created_w" -gt 1200 ] || [ "$max_created_h" -gt 1200 ]; then
        if [ "$src_w" -ge "$src_h" ]; then
            fallback_w=1200
            fallback_h=$(( src_h * 1200 / src_w ))
        else
            fallback_h=1200
            fallback_w=$(( src_w * 1200 / src_h ))
        fi
    fi

    local fallback_ext="jpg"
    [ "$has_alpha" -eq 1 ] && fallback_ext="png"

    local fallback_file="$img_dir/${base}-fallback.${fallback_ext}"

    if [ "$fallback_ext" == "png" ]; then
        magick "$work" -resize "${fallback_w}x${fallback_h}" "$fallback_file"
        log_output+="      ↳ Оптимизируем палитру уменьшенного PNG-фолбэка...\n"
        pngquant --quality=40-85 --speed=1 --force --output "${fallback_file%.png}_tmp.png" "$fallback_file" \
            && mv "${fallback_file%.png}_tmp.png" "$fallback_file" || true
        oxipng -o 6 --strip safe --quiet "$fallback_file" || true
    else
        magick "$work" -strip -units PixelsPerInch -density 72 \
            -resize "${fallback_w}x${fallback_h}" -quality 65 "$fallback_file"
    fi

    local fallback_final_size=$(stat -c %s "$fallback_file" 2</dev/null || echo 0)
    local pretty_size=$(numfmt --to=iec "$fallback_final_size")
    log_output+="      ✓ Создан дефолтный фолбэк: ${base}-fallback.${fallback_ext} [${fallback_w}x${fallback_h}] ($pretty_size)\n"

    # Удаляем оригинал из входящей папки и временную рабочую директорию
    rm -f "$input"
    rm -rf "$tmp_work_dir"

    # --- Подготовка списков существующих файлов для умного srcset ---
    local valid_avif=()
    local valid_webp=()
    for size in "${SIZES[@]}"; do
        [ -f "$img_dir/${base}-${size}.avif" ] && valid_avif+=("$size")
        [ -f "$img_dir/${base}-${size}.webp" ] && valid_webp+=("$size")
    done

    # Общая строка sizes для обоих тегов source
    local sizes_attr="sizes=\"(max-width: 640px) 100vw, (max-width: 1200px) 80vw, 1200px\""

    # Генерируем HTML блок в лог
    log_output+="\n → HTML для вашего файла:\n"
    log_output+="   <picture>\n"

    # Блок AVIF
    log_output+="     <source type=\"image/avif\" srcset=\"\n"
    local len_avif=${#valid_avif[@]}
    for ((i=0; i<len_avif; i++)); do
        local size=${valid_avif[i]}
        if [ $i -eq $((len_avif - 1)) ]; then
            # На последней итерации закрываем кавычку, переносим строку и пишем sizes
            log_output+="       img/${sub_dir}/${base}/${base}-${size}.avif ${size}w\"\n     $sizes_attr>\n"
        else
            log_output+="       img/${sub_dir}/${base}/${base}-${size}.avif ${size}w,\n"
        fi
    done

    # Блок WebP
    log_output+="     <source type=\"image/webp\" srcset=\"\n"
    local len_webp=${#valid_webp[@]}
    for ((i=0; i<len_webp; i++)); do
        local size=${valid_webp[i]}
        if [ $i -eq $((len_webp - 1)) ]; then
            # На последней итерации закрываем кавычку, переносим строку и пишем sizes
            log_output+="       img/${sub_dir}/${base}/${base}-${size}.webp ${size}w\"\n     $sizes_attr>\n"
        else
            log_output+="       img/${sub_dir}/${base}/${base}-${size}.webp ${size}w,\n"
        fi
    done

    # Блок IMG фолбэка
    log_output+="     <img src=\"img/${sub_dir}/${base}/${base}-fallback.${fallback_ext}\" width=\"$fallback_w\" height=\"$fallback_h\" alt=\"Опиши картинку здесь\" loading=\"lazy\">\n"
    log_output+="   </picture>\n"

    # Выплескиваем весь лог картинки атомарно, чтобы строки не перепутались
    echo -e "$log_output"
}
export -f process_single_image

# ==================== ДИСПЕТЧЕР ПОТОКОВ ====================
files=("$SCRIPT_DIR"/*.{jpg,jpeg,png,webp,avif,JPG,JPEG,PNG,WEBP,AVIF})

if [ ${#files[@]} -eq 0 ]; then
    echo "❌ Ошибка: В папке '$SCRIPT_DIR' не найдено файлов картинок для обработки!"
    exit 1
fi

echo "🚀 Запуск параллельной обработки (Лимит: 5 потоков)..."

MAX_JOBS=5

for input in "${files[@]}"; do
    [ -e "$input" ] || continue

    # Запускаем обработку одной картинки строго в фоновом режиме (&)
    process_single_image "$input" &

    # Считаем, сколько фоновых задач запущено прямо сейчас
    # Каждый раз, когда количество фоновых задач достигает максимума,
    # команда 'wait -n' приостанавливает цикл, ожидая завершения ЛЮБОЙ одной задачи.
    while [ "$(jobs -r | wc -l)" -ge "$MAX_JOBS" ]; do
        wait -n
    done
done

# Ждем завершения последних "хвостов" в очереди
wait

echo ""
echo "=== Все картинки обработаны параллельно и разложены по полочкам! ==="

                    

Первые шажки в CSS

Прочитав заголовок, можно подумать, что я разобрался с курсом от FreeCodeCamp по HTML, но не тут-то было! Пока я возился с ИИ со скриптом, Джеминай так и норовил мне надавать разных советов, что и как можно сделать симпатичнее; потом мне самому стало любопытно, как расстояние увеличить между ссылками в хедере, как сделать отступы у абзацев и всё-всё-всё… В итоге я теперь знаю, как отмечаются в селекторах классы, айди и теги в CSS-файле и некоторые свойства типа text-align и font-size. Не смейтесь, все с чего-то начинают! 🤓☝️

Что ж, на сегодня, кажется, всё. Пора публиковаться на гитхабе!

Так, уже этот абзац пишется после первого коммита. Выяснилось, что на Github Pages относительные пути от корня — типа /img/day_1/akihabara000/akihabara000-640.avif не работают! Это происходит потому, что гитхаб начинает рыскать не в корневой директории репозитория https://wokolai.github.io/personal-site, а в корневой директории моего сайта https://wokolai.github.io. Теперь стремительно меняю все абсолютные пути либо на голые относительные img/day_1/akihabara000/akihabara000-640.avif (идеально для сайтов в корневой папке), либо на ../../../../img/day_1/akihabara000/akihabara000-fallback.jpg (для файлов в архивной директории); выглядит последнее несуразно, по-моему, но зато работает и на реальном сервере, и на гитхабе. Также решил проверить сайт на валидаторе, как это рекомендовал делать парень с курса, который я прохожу, и нашёл у себя кучу ошибок, которые также стремительно исправил. Ну и ещё пару 💫 косметических изменений 💫 сделал, в частности убрал скругление на обводке моего диалога с Клодом — она вообще пока не нужна. Теперь, будучи более осознанным и подготовленным, делаю второй коммит!

День 4: таблицы и забота о здоровье

Дата публикации:

Таблицы

Всем привет! Я пережил экзамен по математике и только сейчас возвращаюсь к работе над сайтом и изучению HTML. В последний раз я остановился на таблицах. Не понял некоторые моменты и хочу остановиться на них поподробнее.

Покажу вам, какой ноут удалось взять на Авито за 80000 ₽. :D

ASUS TUF Gaming A15 FA507NV (модифицированный)
Процессор AMD Ryzen 5 7535HS
Встроенная видеокарта AMD Radeon 660M
Дискретная видеокарта NVIDIA GeForce RTX 4060 Laptop GPU (140 Вт)
Оперативная память DDR5 Kingston FURY Impact [KF556S40IB-16] 16 ГБ x 2
SSD WD PC SN740 SDDPNQD-512G-1002
ADATA LEGEND 860
Ёмкость аккумулятора 90 Вт*ч
Оставшаяся ёмкость аккумулятора 87 %

Если честно, доволен покупкой, как слон!

Забота о здоровье глаз и рук

Сегодня значительную часть дня я потратил на выстраивание стратегии «безвредного» досуга за ПК. Что я имею в виду? Ни для кого не секрет, что проводить сутки перед монитором не очень полезно. Это влияет и на здоровье глаз, и на здоровье рук, и на здоровье спины. Со спиной мне ещё предстоит разбираться (пока нет возможности реализовать всё это грамотно), но с глазами и руками, особенно дома, справиться можно.

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

  • Правило 20-20-20

    Незамысловатое предложение, данное в девяностые годы прошлого века оптометристом Джеффри Аншелом, гласит, что каждые 20 минут надо 20 секунд фокусировать взгляд на предмете, находящемся на расстоянии 20 футов (~6 метров). Чтобы его соблюдать, я из Flathub скачал Stretchly — утилиту, которая раз в заданные промежуток времени блокирует экран, чтобы человек мог сделать свои дела со глазами. Я настроил его так, чтобы раз в час также был перерыв на 5 минут — это необходимо для полноценной разминки.

  • Разминка для глаз

    Полная разминка для глаз, которую я теперь делаю раз в час работы за ноутом, указана далее. Как раз отточу навык создания таблиц!

    Моя разминка для глаз
    Упражнение Затрачиваемое время (в секундах)
    Пальминг
    Движения вверх-вниз
    Движения вправо-влево
    Круговые движения по часовой стрелке
    Круговые движения против часовой стрелки
    Поморгать
    Вблизь-вдаль (по 3 секунды)
    Закрыть глаза

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

  • Расположение монитора (в моём контексте экрана ноутбука)

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

  • Моргать

    Тут, пожалуй, самое сложное… В процессе работы перед экраном надо не забывать моргать. У меня это получается не очень хорошо, ведь я часто фокусируюсь на том, что делаю, а не на моргании. Мне есть куда расти!

Дальше можно поговорить о здоровье рук, и тут будет полезное предоставить некоторую историю. В период с по я любил проводить время в ритм-игре osu!, где нужно было одной рукой наводиться стилусом на кружочки и другой рукой жать две кнопки (всё это под отличную музыку). Как иногда бывает, я делал это очень неаккуратно: сильно прижимал запястья к столу, неправильно держал стилус (да, бывают разные хваты, и я выбрал один из самых неэргономичных). В итоге у меня начали болеть запястья, и я оставил игру. Потом боль почти полностью исчезла и достигла едва заметного плато, которое я не хочу ухудшать. Сейчас у меня есть сплит-клавиатура со встроенным трекболом и на крайние случаи вертикальная мышь. Эти девайсы сами по себе ставят запястья в куда более естественное положение, но, очевидно, чтобы сократить потенциальные разминки, рекомендуется делать разминки. Раз в час я обращаюсь к популярной в осу-сообществе видеоинструкции от Tykato Fitness. Удачи мне; надеюсь, не заброшу эту историю. :')

Дни 1, 2 и 3: первые потуги

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

Снапшоты сайта по дням