Обновить

Фронтенд

Сначала показывать
Порог рейтинга

Почему стоит использовать protected в Angular компонентах?

Если вы используете в своих компонентах только public и private, вы упускаете возможность сделать архитектуру чище. Я предлагаю четко разделять ответственность членов класса.

Часто мы по инерции делаем public любые методы и свойства, которые нужны в шаблоне (HTML). Но public в TypeScript означает, что это публичный API компонента - к этим методам может получить доступ любой родительский компонент через @ViewChild.

Почему стоит использовать protected:

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

2. Защита от регрессии: Если другой разработчик попытается вызвать такой метод через @ViewChild, TypeScript выдаст ошибку. Это заставит его задуматься: «Действительно ли мне нужно делать этот метод публичным?» или «Может, стоит создать отдельный метод для API?».

3. Читаемость: Открывая код, вы сразу видите: public - для внешнего мира, protected - для шаблона, private - для внутренней логики сервисов и подписок.

Разделяйте Public API и внутреннюю логику шаблона - ваш код станет надежнее и понятнее.

@Component({
  selector: 'app-user-profile',
  template: `
    <!-- В шаблоне мы без проблем обращаемся к protected свойствам -->
    <div class="card">
      <h3>{{ userName() }}</h3>
      <button (click)="onUpdateClick()">Обновить</button>
        @if(isLoading()) {
          <div>Загрузка...</div>
        }
    </div>
  `
})
export class UserProfileComponent {
  // PRIVATE: Внутренняя логика. 
  // Не доступно ни в шаблоне, ни родительскому компоненту.
  private _userId = 123;

  // PROTECTED: Доступно только внутри класса и в ШАБЛОНЕ.
  // Идеально для переменных состояния UI и обработчиков событий.
  protected userName = signal('Алексей');
  protected isLoading = signal(false);

  protected onUpdateClick(): void {
    this.logAction();
    console.log('Кнопку нажали в шаблоне');
  }

  // PUBLIC: Публичный API компонента.
  // Только эти методы мы разрешаем вызывать родительскому компоненту.
  public resetState(): void {
    this.userName.set('Гость');
    this.isLoading.set(false);
  }

  private logAction(): void {
    console.log(`Action logged for userId: ${this._userId}`);
  }
}
Теги:
Всего голосов 2: ↑2 и ↓0+2
Комментарии1

пет-проект невозможно доделать - только выпустить в открытую бету

Что ж, встречайте открытую бету проекта

📚📚📚📚📚📚📚📚📚📚
SweetReader!
📚📚📚📚📚📚📚📚📚📚

Что это:
Пространство для авторов и читателей, упор сделан на книги с высоким уровнем визуала (графические романы, комиксы, манги, книги с упором на иллюстрации). 

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

На текущий момент это MVP - буквально базовая версия продукта, есть планы по его доработке и даже (о, ужас) "дорожная карта", которую, может быть, я реализую )))

_____

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

Буду рад обратной связи тут в комментариях. Если найдёте баг или ошибку (а это на текущей стадии несложно), в меню есть кнопка "Ошибка?" специально для неравнодушных пользователей.

Теги:
Всего голосов 2: ↑0 и ↓2-2
Комментарии0

Lex Kravetski в ФБ написал оду Микрософт Ворду, с которым у меня плохие отношения еще с конца 1980-х, когда он был под DOS-ом в графическом режиме. Причем тогда Ворд был еще более-менее, хотя бОльшая часть его функциональности лично мне не была нужна, для форматированных текстов хватало Лексикона от Eugene Veselov из ВЦ Академии Наук, затем уехавшим в Микрософт и ныне ставшим очень политизированным.

Главные проблемы с Вордом для меня начались после 2000 года, когда у него стало прыгать форматирование невпопад, особенно в текстах с комбинацией списков, таблиц и картинок. Lex такую проблему упоминает с позиции своих оппонентов: "блин, даже пробел в нём как-то странно работает, по коей причине даже простое форматирование сделать тяжело."

Из-за этого прыгания я сейчас для редактирования форматированных текстов как правило использую простой текстовый редактор joe (который имитирует редактор в TurboC 1988 года, но с квадратными блоками), а в нем - .md Markdown, который потом конвертирую в .pdf с помощью программы pandoc.

Также использую Google Doc, в нем форматирование не прыгает, как в Microsoft Word и в Libre Office, а сделано по человечески.

Раньше еще писал в текстовом редакторе на HTML, но Markdown удобнее, так как читабильнее в голом виде. Если вы еще не выучили Markdown и мучаетесь Вордом - просто нагуглите его в википедии, он учится за 15 минут.

Теги:
Всего голосов 8: ↑7 и ↓1+6
Комментарии12

Как получить почти бесконечное зацикливание без использования циклов и без переполнения стека вызовов:

// Установите N = 64, и эта функция никогда не завершится  
// Количество вызовов (calls) = 2^(N+1)  
// Максимальная глубина вложенности = N

let calls = 0
const N = 18
function func(state, visited) {
  calls++
  if (calls > 10_000_000) {
    throw new Error('calls: ' + calls)
  }
  if (visited.includes(state)) return

  const newVisited = [...visited, state]

  func((state + 1) % N, newVisited)
  func((state + 1) % N, newVisited)
}

func(0, [])
console.log('calls:', calls)

Почему это работает без переполнения стека?

func(0, [])
├── func(1, [0])
│   ├── func(2, [0,1])
│   │   └── ... глубина растёт до N
│   │           и перебираются все возможные комбинации значений в newVisited
│   └── func(2, [0,1]) - возвращается, глубина УМЕНЬШАЕТСЯ
└── func(1, [0])       - второй вызов, стек уже освободился

А Garbage Collector (GC) при этом бесконечно удаляет созданные ранее массивы newVisited

Стек "дышит" - достигает максимума N, потом сворачивается, потом снова растёт. Это обход огромного дерева, имеющего небольшую глубину, но очень большую ширину. Это не бесконечная рекурсия. Но при N = 64 количество вызовов будет 2^65 (примерно 10^19) - это займёт тысячи лет, и стек никогда не переполнится.

Теги:
Всего голосов 1: ↑1 и ↓0+1
Комментарии2

Коллеги, всем привет!

За годы менторства по Angular (в том числе в HTML Academy) я заметил одну системную проблему: студенты и даже миддлы часто знают синтаксис RxJS, но не понимают реактивного мышления. В итоге мы получаем subscribe внутри subscribe и императивную лапшу.

Я искал интерактивные курсы, но большинство бесплатных ресурсов ограничиваются основами.

Курс бесплатный. Делал для себя и студентов, но теперь делюсь со всеми.

Буду рад фидбеку и баг-репортам (проект активно допиливаю).

Ссылка на курс: https://rxjs-course-avy.web.app/

Теги:
Всего голосов 7: ↑7 и ↓0+8
Комментарии1

Команда разработчиков Chrome собрала на одной странице все крупные изменения в CSS за 2025 год. У каждой новой фичи есть подробное описание, интерактивная демонстрация, примеры кода и информацию о поддержке в основных браузерах.

Теги:
Рейтинг0
Комментарии0

Друзья, классная новость! Мы с коллегами из GitVerse закончили разработку интеграции! 

Теперь в Gramax можно подключить GitVerse в качестве хранилища. Работает в лучшем виде: клонирование, синхронизация, коммит, пуш — все как и должно быть ✨

Это была масштабная и интересная работа: мы вместе анализировали API, чтобы получилось максимально удобно. Потому будем очень рады увидеть ваши плюсики!

Gramax — Open Source-платформа для работы с документацией в подходе Docs as Code. GitVerse — AI-first платформа для работы с кодом.

Теги:
Всего голосов 3: ↑2 и ↓1+3
Комментарии0

React One Click Component

Поделюсь самодельным расширением для VS Code, которое позволяет создавать React-компоненты в один клик.

Демонстрация работы расширения
Демонстрация работы расширения

Что умеет:

  • гибкое именование файлов: выбор между PascalCase, camelCase, kebab-case или snake_case для генерируемых файлов;

  • работа с .tsx и .jsx для файлов компонентов, а также .scss, .css, .less и .sass для стилей;

  • редактируемые шаблоны: настройка содержимого генерируемых файлов прямо в VS Code;

  • опциональное создание файлов реэкспорта и стилей.

Более подробный readme на странице расширения, ссылка на исходники там же. На мой взгляд экстешнен написан таким образом, что его довольно легко переписать для любого web-фреймворка.

На всякий случай: ни с какими внешними сервисами и нейронками расширение не взаимодействует)

Теги:
Всего голосов 2: ↑2 и ↓0+4
Комментарии0

Массовая замена HTML-разметки в Sublime Text с помощью RegExp

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

В моём случае это были заглушки вида:

<p>Image 1</p>
<p>Image 2</p>
<p>Image 3</p>

Нужно было превратить их в теги изображений, сохранив номера файлов изображений.

Почему не руками

Ручная правка подходит только для пары строк. Когда элементов больше 10–20, возрастает риск:

  • ошибиться в номере изображения

  • забыть закрыть тег

  • нарушить единообразие разметки

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

Решение через Sublime Text и RegExp

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

Открываем HTML-файл и вызываем панель замены:

  • Ctrl + H (Windows / Linux)

  • Cmd + Alt + F (macOS)

Обязательно включаем режим Regular Expression (иконка .*).

Шаблон поиска

<p>Image (\d+)</p>

Разберём выражение:

  • <p>Image — фиксированная часть

  • (\d+) — группа захвата, которая находит любое число

  • </p> — закрывающий тег

Число внутри скобок сохраняется как первая группа.

Шаблон замены

<img src="images/\1.jpg">

Здесь \1 — ссылка на первую группу захвата из шаблона поиска. На её место подставляется найденное число.

В результате:

  • Image 1images/1.jpg

  • Image 12images/12.jpg

Проверка и замена

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

После этого можно смело использовать Replace All — Sublime Text заменит все подходящие строки за один шаг.

Подводные камни

Несколько моментов, о которых легко забыть:

  • если не включить RegExp, \1 подставлен не будет

  • в Sublime используется именно \1, а не $1

  • шаблон чувствителен к пробелам и регистру

Альтернативы

Для подобных задач подойдут и другие инструменты:

  • sed в терминале

  • массовая генерация HTML через bash-циклы

  • аналогичная замена в VS Code

Но если файл уже открыт в Sublime Text, RegExp — самый быстрый вариант.

Вывод

Регулярные выражения в Sublime Text позволяют эффективно автоматизировать рутинные правки HTML без дополнительных скриптов и плагинов. Даже простые приёмы вроде групп захвата экономят время и снижают количество ошибок.

Дополнительно

Более подробная пошаговая инструкция с ориентацией на новичков опубликована в моём блоге:

https://kodprog.ru/kak-bystro-zamenit-tekst-na-tegi-img-v-sublime-text

Теги:
Всего голосов 1: ↑1 и ↓0+3
Комментарии3

Доброго всем. Первая публикация, прошу не особо...

Не стану растекаться мыслью по древу, пост - следствие поиска по запросам типа "как лучше вставить и анимировать SVG иконки", и подобным в том же ключе. Так как самыми релевантными ответами поиска не удовлетворён, решил написать свой, во-первых, чтобы услышать сообщество. Мало ли, возможно технология уже вовсю применяется в фреймворках, и на поиск все забили "всё и так слишком очевидно".
Во-вторых, сам до сих пор копаюсь в ванильном, поэтому, если старшие товарищи найдут сей вариант приемлемым, пусть пост останется как справка, вроде "а чё, так можно было?". Если же такая практика не применима по ряду пока неизученных мной причин, пост тоже пусть остаётся дополненный комментариями, как пример того "как не надо делать". В общем.

Решил упаковать спрайт в Web Components. Для примера взял отображение файловых иконок, за подопечных три распространённых файловых формата .docs, .xls, .pdf. Раз уж мне и так пришлось испытать муки отсутствия музы( вообще ни разу не художник), прошу отнестись с пониманием к внешнему виду конечного продукта. Упор был на простоту, контролируемость, компоновку. В том смысле, что косметика человеком с утончённым восприятием этого мира может быть применима отдельно.
Да, и ещё один аспект постарался обыграть - наличие общих свойств для всех иконок, коими выбрал подложку, и текст mime типа, и уникальные для каждой иконки элементы, ими выступили "брендовые" цвета и элементы. Так, выбор иконок файловых форматов для спрайта показался оптимальным.
Далее, в общем код(сокращённо, рабочий пример по ссылке), совсем немного к нему объяснений и ссылка на песочницу. И, само собой, ожидание комментариев.

customElements.define("wc-icon-file",
  class WC_ICON_FILE extends HTMLElement {
    constructor() {
      super();
      this.#preform = '';
      this.#mime = '';
      this.#unic = '';      
    }  
    connectedCallback() {
      this.init();
      this.innerHTML=this.#preform;
    } 
    init() {
      this._mime = this.getAttribute('data-mime');
      let availableMime = {
        xlsfile: `<g class="wc-icon-${this.#mime}">
          <line style="stroke-width:3;stroke-linecap:butt;" x1="13" x2="17" y1="24" y2="24"/>
          <line style="stroke-width:3;stroke-linecap:butt;" x1="18" x2="22" y1="24" y2="24"/>
          // и т.д.
          <text x="8" y="19" class="f-mime">.xls</text>
          </g>`,
        docfile: `<g class="wc-icon-${this.#mime}">
          <line style="stroke-width:1.8;stroke-linecap:round;" x1="20" x2="24" y1="23" y2="23"/>
          <line style="stroke-width:1.3;stroke-linecap:round;" x1="16" x2="30" y1="27" y2="27"/>
          // и т.д.
          <text x="8" y="19" class="f-mime">.doc</text>
        </g>`,
          pdffile: `<path class="wc-icon-${this.#mime}" d="m 21.963376,23.938571 // и т.д. />
          <text x="8" y="19" class="f-mime">.pdf</text>` 
        }      
        this.#unic = availableMime[this.#mime];
        this.#preform = `<svg class="wc-icon-file" viewBox="0 0 48 48">
           <path class="${this.#mime}" d="M13.528 3.087 30 3l8 9-.316 28.075c-.035 3.151-1.09 
            4.143-3.716 4.11h-20.44 c-2.303.095-3.676-.718-3.716-4.11V7.197c-.03-2.459
            1.504-4.198 3.716-4.11z"/>
            ${this.#unic}
            </svg>`
  }; 
});
let wcIconFile = document.createElement('wc-icon-file');
// export {wcIconFile} по необходимости

Сам компонент на странице объявляется как обычно:

<wc-icon-file data-mime="xlsfile"></wc-icon-file>
<wc-icon-file data-mime="docfile"></wc-icon-file>
<wc-icon-file data-mime="pdffile"></wc-icon-file>    

Код прокомментирую на предмет того, что в init() пришлось соблюсти порядок объявления переменных. Для определения схожих классов с разными "модификаторами" сначала брался атрибут в компоненте. По нему же делалась выборка this.#unic впоследствии вставляемая в this.#preform . Стили здесь не привожу, отмечу лишь, что настройки :hover и анимации там вполне работают.

Благодарю, что уделили время.

Теги:
Всего голосов 2: ↑2 и ↓0+3
Комментарии3

Google представил топ лучших расширений для Chrome в 2025 году: 

  • HARPA AI: позволяет автоматизировать любую работу в интернете: мониторинг сайтов, напоминания, боты, поиск, скрапинг; 

  • Quillbot: если работаете с текстом — это вам. Проверка орфографии, рерайт ИИ‑текста, подборка синонимов и даже проверка осмысленности текста;

  • Monica и Sider: добавляют в браузер боковую панель с самыми полезными нейронками. Удобный доступ к сразу нескольким чат‑ботам, быстрой генерации картинок и видео, проверке и переводу документов; 

  • Fireflies и Bluedot: помогут в создании заметок и автоматической расшифровке бесконечных созвонов; 

  • QuestionAI и eJOY: школьники и студенты, а это вам — помощник по выполнению домашних заданий и разбору тем по любым предметам. 

  • Adobe Photoshop: быстрый доступ к Фотошопу. Веб‑версия проще, но там есть все нужные инструменты для редактирования фотографий, в том числе ИИ‑фотошоп;

  • Phia: шопинг‑расширение с ИИ для автоматического сравнения цен при покупках в браузере. Идеально, если все ещё мечтаете найти дешёвые ОЗУ.

Теги:
Рейтинг0
Комментарии0

Похоже, того фронтендера, который знал, что такое margin, уже оптимизировал "Режим ИИ". Либо вайбкодинг есть - поэтому отступов нет 😅

Теги:
Всего голосов 5: ↑5 и ↓0+8
Комментарии0

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

Несмотря на это, i18next остаётся решением по умолчанию, которое ChatGPT рекомендует для внедрения i18n. Мы слишком часто попадаемся на удочку страниц «Get Started» (да, оно работает, но действительно ли это сделано правильно?).

На практике я замечаю, что многие проекты пропускают самые критичные аспекты интернационализации, особенно связанные с SEO: перевод метаданных, теги hreflang, локализация ссылок, настройка sitemap и robots.txt.

Что ещё хуже, почти половина проектов, использующих i18next (особенно после роста популярности ИИ), не структурируют контент по неймспейсам или же загружают все неймспейсы при каждом запросе.

Последствия? Вы можете заставлять каждого пользователя загружать контент всех страниц на всех языках, даже если он посещает только одну страницу. Например: при 10 страницах и 10 языках 99% загружаемого контента никогда не будет использовано. Совет: используйте анализатор бандла, чтобы выявить это.

Чтобы решить проблему, я подготовил руководство о том, как правильно интернационализировать приложение Next.js 16 с i18next в 2025 году.

Вот ссылка: https://intlayer.org/ru/blog/nextjs-internationalization-using-next-i18next

Теги:
Всего голосов 1: ↑1 и ↓0+1
Комментарии0

Ближайшие события

Представлен ИИ-сервис Vibetest Use, который тестирует сайты на прочность и ищет уязвимости. Параллельно запускаются сразу несколько проверок с помощью ИИ, которые ищут ошибки, битые ссылки или проблемы в дизайне. Работает на базе Claude. В качестве альтернативы можно запустить с бесплатным API от Google через Cursor.

Теги:
Всего голосов 2: ↑1 и ↓10
Комментарии1

Как мы избавились от рутины в сетевом коде с помощью собственного фреймворка Chord 🪄

Расскажем на крупнейшей конференции для разработчиков разного профиля — Holly JS 🤟

Спикером конференции станет Дмитрий Дин, fullstack-лид Далее. В докладе «Chord’овская декларативность: побеждаем бойлерплейт сетевого взаимодействия» он поделится опытом внедрения собственного инструмента Chord (на базе JSON-RPC), который уже больше года работает в продакшене и избавляет команды от рутины при взаимодействии между клиентом и сервером. 

Доклад будет особенно полезен frontend- и fullstack-разработчикам (уровня Middle и выше), которые работают с TypeScript и современными фреймворками вроде SvelteKit, Next.js или Nuxt. 

Приходите послушать доклад Димы 21 ноября, с 15.30, в секции Фреймворки. 

🔗 Подробнее о докладе и спикере — на сайте Holy JS.

Теги:
Рейтинг0
Комментарии0

Представлен открытый проект релейного компьютера 1961 года Minivac 601, работающий в браузере (код на GitHub). До появления микрочипов компьютеры строились на основе механических реле. Это рабочая модель Minivac 601, образовательного компьютера, разработанного Клодом Шенноном.

Теги:
Всего голосов 5: ↑4 и ↓1+4
Комментарии1

Представлена шпаргалку по JavaScript. Внутри есть всё для изучения, проверки себя и прокачки навыков до уровня сеньора: основы и теория, поиск и выбор элементов, CSS, AJAX и база по DOM, формы и ввод данных, общие проверки , разметка и текстовое содержание, документ, область просмотра, переходы и удобный поиск по всем темам.

Теги:
Всего голосов 3: ↑3 и ↓0+3
Комментарии1

minimal vscode - гайд по кастомизации vscode: чистим status bar, пишем плагины на #javascript

В статусбаре в vscode – очень много всего: как полезного, так и лишнего.
Сегодня посмотрим, как можно его кастомизировать:

  • Можно просто спрятать (как делаю я)

  • Можно очень детально кастомизировать

  • Можно перенести часть его функций в плагины

И вот тут главная фича vscode выходит наружу – у нас ведь просто браузер с html / css / js. А значит, мы можем использовать css и js для кастомизации всего! И оно будет работать одинаково даже в cloud версиях IDE.

В выпуске:

  • Будем писать CSS для удаления лишнего из status bar

"custom-ui-style.stylesheet": {
  "#status\\.problems": {
    "visibility": "hidden !important",
    "display": "none !important",
  }
}
  • И создавать локальные плагины на #javascript для кастомизации поведения редактора

function updateColumnPosition() {
    const positionLabel = document.querySelector(
      '#status\\.editor\\.selection .statusbar-item-label',
    )
    if (!positionLabel || !positionLabel.textContent) {
      // It might not exist for some reason ¯\_(ツ)_/¯
      return
    }

    const currentLine = document.querySelector(
      '.line-numbers.active-line-number',
    )

    // Now we would have the column position instead of the active line number:
    const colNumber = positionLabel.textContent.match(/Col (\d+)/)
    currentLine.textContent = colNumber[1]
}

Впереди еще пара взрывающих мозг видосов, будем и дальше превращать vscode в Черный Квадрат Малевича.

Теги:
Всего голосов 2: ↑2 и ↓0+2
Комментарии2

Лучший стэк для запуска MVP SaaS-стартапа в РФ на 2025 год.

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

Проверено на собственной шкуре!

Frontend:

- NextJS 15 (+React 19, Turbopack, Server Actions) - актуальный стек для веб-приложений.

- Shadcn UI (сделана на Tailwind) - библиотека UI-компонентов, чтобы сделать крутой интерфейс без дизайнеров.

- Netlify - бесплатный хостинг для тестовой версии продукта.

Backend:

Supabase:

- База данных

- Database SQL Functions (функции сразу в базе PostgreSQL)

- Edge Functions (серверные функции на TypeScript)

Nextauth:

- Авторизация

Инфраструктура:

Kubernetes:

- Репликация БД и сервисов на 3-х Worker-нодах

- Rollout-обновления без простоя

- Политики безопасности и изоляция

- CI/CD из GitHub.

+ Пароли/ключи в KeePass XC.

Инструменты:

- IDEA Ultimate - среда разработки

- Cursor - для вайбкодинга (чистый, без всяких инфоцыганских MCP)

- DBeaver - для работы с БД

- GitHub - репозиторий

Платежка

- Robokassa (РФ + иностранные платежи)

Лендинг + блог

- Tilda (проще сделать сайт на конструкторе, чем все это вайбкодить)

Как мы все настроили

- Развернули проект в облачном хостинге в РФ, чтобы хранить данные в соответствии со 152 ФЗ. Выбрали хостинг с k0s, потому что он дешевле классического k8s.

- Supabase поставили на свой сервер (Cloud не подходит, так как данные хранятся не в РФ).

- Настроили регулярные бэкапы (хотя мы еще не релизились, но 1 раз у нас уже отлетали жесткие диски).

Почему именно такой стэк?

- Проще работать с технологиями, которые ты уже хорошо знаешь.

- Нам важна надежность, быстрое переключение новых версий на проде без простоя и возможность разделить продукт на версию под РФ и "мир".

- Для работы в РФ нужно хранить персональные данные в РФ и избегать трансграничной передачи данных.

- Конструктор сайтов как простой и недорогой вариант для лендингов и блога. Чтобы не вайбкодить целую CMS.

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

А какие технологии используете вы для разработки MVP?

Теги:
Всего голосов 3: ↑2 и ↓1+1
Комментарии7

Рецепт качественного фронтенда:

Возьмите три ингредиента: HTML для чёткой структуры, CSS для красивого оформления и JavaScript для динамики. Смешайте всё в нужных пропорциях, добавьте немного практики, щепотку креатива — и получится интерфейс, которым приятно пользоваться.

А если хотите разобраться во всём шаг за шагом — ловите подборку по основным инструментам топового фронтенд-разработчика:

HTML

CSS

JavaScript

→ Еще больше полезного на нашей витрине

Теги:
Всего голосов 1: ↑1 и ↓0+1
Комментарии0