Поиск первопричины ошибки в CSS

Поиск первопричины ошибки в CSS

От автора: как фронт-энд разработчик, вы сталкивались с множеством ошибок CSS, которые могут помешать пользователю завершить или успешно выполнить свою задачу. Ошибка CSS может быть визуальной или технической, и оба этих типа могут повлиять на взаимодействие с пользователем. Иногда вы торопитесь и у вас нет времени на полную отладку и исправление ошибки, поэтому вы работаете над быстрым решением, которое устраняет ошибку только извне.

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

Работая над своей книгой «Отладка CSS», я много узнал об отладке и исправлении ошибок CSS. В этой статье я рассмотрю процесс исправления первопричины ошибки и исследую некоторые распространенные проблемы CSS, а также то, как их исправление извне может привести к большему количеству проблем.

Базовый пример

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

Предположим, у нас есть сетка из карточек, которая является распространенным шаблоном в сети. У вас есть изображение, которое должно иметь такую же ширину, что и его родительский элемент (карточка). Для этого вы добавили к изображению следующее правило CSS:

.card__img { width: 100%;
}

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

Поиск первопричины ошибки в CSS

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

Поиск первопричины ошибки в CSS

Мы действительно хотим получить это? Это похоже на макет Mansory, но цель этого макета — ограничить компоненты карточек определенным размером. Карточки не должны быть выше друг друга. Вот быстрое решение этой проблемы:

.card__img { width: 100%; height: 200px;
}

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

Поиск первопричины ошибки в CSS

Как видите, добавление height частично решило проблему и привело к тому, что высота компонентов была одинаковой. Однако это вызвало еще более серьезную проблему — сжатие вертикального изображения. Как фронт-энд разработчик, вы обязаны задавать множество вопросов, которые позволят вам понять, как именно должен работать и вести себя компонент.

Вот несколько вопросов, над которыми стоит задуматься:

Должны ли компоненты карточки быть одинаковой высоты?

Каков ожидаемый размер миниатюры карточки?

Нужно ли разрешать авторам контента загружать изображения большего или меньшего размера?

Ответы на эти вопросы могут меняться от проекта к проекту. Я хочу, чтобы это было похоже на настоящий проект, поэтому я отвечу на них за вас.

Да, они должны быть одинаковой высоты.

330 пикселей * 220 пикселей.

Нет, размер изображения должен быть одинаковым.

А теперь давайте посмотрим, как исправить проблему. Применяя object-fit: cover к изображению, мы можем гарантировать, что изображение не будет сжато.

.card__img { width: 100%; height: 220px; object-fit: cover;
}

Я знаю, что размеры изображений должны быть одинаковыми, но добавление object-fit может предотвратить нежелательные проблемы в будущем. И, наконец, вопрос, над которым я должен подумать: можно ли скрыть некоторые части изображения? Использование object-fit не сделает изображение сжатым, но, с другой стороны, оно изменит размер изображения, чтобы оно соответствовало указанной ширине и высоте, и это может скрыть некоторые его части.

Вот как будет выглядеть высокое изображение с object-fit: cover.

Поиск первопричины ошибки в CSS

Обратите внимание, что некоторые части второго изображения скрыты. Это ожидается, и это можно решить, изменив свойство object-position следующим образом:

.card__img { width: 100%; height: 220px; object-fit: cover; object-position: center 75%;
}

Хотя это решает проблему, это непрактично. Мы не можем добавить определенное object-position для каждой миниатюры в проекте.

Поиск первопричины ошибки в CSS

Некоторые могут возразить, что нам не следует скрывать части изображений, поскольку мы платим большие деньги за их съемку и редактирование. В таком случае единственное, что вы можете сделать — это объяснить, что это не ваша проблема и что размеры изображения должны быть согласованы.

Теперь, когда я объяснил базовый пример, давайте рассмотрим другие сценарии, чтобы сделать концепцию поиска основной причины еще более ясной.

Размещение раскрывающегося меню

Сколько раз вам нужно было добавить настраиваемое раскрывающееся меню в компонент заголовка? Я думаю, вы делали это раньше.

Поиск первопричины ошибки в CSS

Выпадающее меню расположено под его родительским элементом. Поскольку раскрывающийся список представляет собой элемент с абсолютно позиционированием, мы можем сделать это, изменив свойство top.

.nav__item { position: relative;
} .nav__dropdown { position: absolute; left: 0; top: 40px;
}

Раскрывающийся список располагается в 40px от верхнего края родительского элемента навигации. Хотя с этим нет проблем, в будущем это может вызвать побочные эффекты. Предположим, вы получили запрос на уменьшение высоты заголовка. В зависимости от того, как вы реализовали навигацию, вам необходимо либо уменьшить вертикальный отступ элемента навигации, либо уменьшить высоту заголовка.

Вы сделали именно это, но забыли проверить, работает ли раскрывающееся меню должным образом или нет. К сожалению, это не так.

Поиск первопричины ошибки в CSS

Это потому, что свойство top имеет фиксированное значение. Лучший способ сделать это — использовать процентное значение. Таким образом, раскрывающийся список останется на своем месте независимо от высоты навигации.

.nav__dropdown { position: absolute; left: 0; top: 100%;
}

Очень хорошее понимание основ CSS может помочь избежать такой ситуации. Использование фиксированного значения для свойства top является ошибкой и не является чем-то, на что можно положиться.

Заменяемые в HTML элементы

Согласно MDN: Заменяемые элементы — это элементы, на содержимое которых не влияют стили текущего документа. С помощью CSS можно изменить положение заменяемого элемента, но не содержимое самого заменяемого элемента.

Абсолютно позиционированное изображение

Примером заменяемого элемента является HTML img. Я хочу рассмотреть менее известные факты, касающиеся его. Предположим, что у нас есть изображение, которое абсолютно позиционировано относительно своего контейнера, но без установки width и height.

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

.card__image { position: absolute; left: 0; top: 0; right: 0; bottom: 0;
}

Вы можете догадаться, что изображение заполнит родительский элемент, потому что оно позиционируется со значением 0 с четырех сторон оболочки. Нет, это не так!

Поиск первопричины ошибки в CSS

Обратите внимание, как изображение выходит за пределы родителя. Причина в том, что изображение является заменяемым элементом, а его ширина по умолчанию соответствует размеру содержимого. По этой причине, вы должны включать свойства width и height.

.card__image { position: absolute; left: 0; top: 0; width: 100%; height: 100%;
}

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

Поиск первопричины ошибки в CSS

Изображение, как флекс-элемент

Поиск первопричины ошибки в CSS

Если вы хотите получить оболочку, содержащую несколько изображений, то с этим также может быть сложно справиться с помощью Flexbox. Предположим у нас есть следующие HTML и CSS:

<div class="wrapper"> <img src="image-1.jpg" alt="" /> <img src="image-2.jpg" alt="" />
</div>

.wrapper { display: flex;
} .wrapper img { flex: 1;
}

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

По умолчанию флекс-элементы не сжимаются меньше минимального размера содержимого (длины самого длинного слова или элемента фиксированного размера). Чтобы изменить это, установите свойство min-width или min-height.

Это означает, что нам нужно заставить флекс-элемент сжиматься меньше минимального размера содержимого, используя min-width (потому что flex-direction в нашем случае равно row).

.wrapper { display: flex;
} .wrapper img { flex: 1; min-width: 0;
}

Вот и все. Мы узнали основную причину проблемы, просто прочитав спецификацию CSS и узнав, как все работает под капотом.

Переполнение и Inline-Block элементы

Я объяснил эту концепцию в своей статье Переполнение в CSS.

Поиск первопричины ошибки в CSS

У нас есть три элемента inline-block, и один из них имеет overflow: hidden. Вы заметите, что кнопка с overflow: hidden не выровнена по базовой линии других элементов.

Согласно спецификации CSS: Базовая линия ‘inline-block’ — это базовая линия его последнего встроенного блока в нормальном потоке, если только он не имеет встроенных блоков в потоке или если его свойство ‘overflow’ имеет вычисленное значение, отличное от ‘visible’, в этом случае базовая линия — это край нижнего поля.

Мне повезло, что Гаэль Пупар упомянул меня в этой проблеме на github в репозитории Bootstrap. Я должен был увидеть вышеупомянутую проблему в реальной жизни!

На странице результатов поиска строка запроса может варьироваться от одного слова до предложения. По какой-то причине в приведенном ниже дизайне строка должна быть ограничена определенной шириной. Для этого автор добавил следующий CSS:

.search-results span { display: inline-block; max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

С этим у нас проблема. Строка запроса не выровнена со смежными элементами. См. рисунок ниже:

Поиск первопричины ошибки в CSS

Без хорошего понимания CSS и тщательного исследования вы можете подумать, что это проблема, связанная с браузером или что-то в этом роде. На самом деле, это естественно. Вот краткое сравнение трех основных браузеров:

Поиск первопричины ошибки в CSS

Как вы заметили, Chrome и Firefox дают одинаковый результат. С другой стороны, Safari показывает другой результат. Вы можете подумать вслух так: «О, это работает в Safari. Тогда проблема в Chrome и Firefox», и затем вы тратите часы на исследование, чтобы наконец обнаружить, что Safari реализует поведение неправильно.

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

.search-results span { position: relative; top: 3px; display: inline-block; max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

Теперь, когда мы знаем первопричину, вот подходящее решение:

.search-results span { display: inline-block; max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: top;
}

Я только добавил vertical-align: top, и проблема решилась мгновенно.

Поиск первопричины ошибки в CSS

Расстояние между смежными элементами

Поиск первопричины ошибки в CSS

Вы работали над созданием веб-сайта и получили отзывы от ведущего дизайнера о том, что расстояние между кнопками непоследовательно. Это 22px вместо 16px. При проверке CSS получается следующее:

<div class="wrapper"> <a class="button" href="">Save changes</a> <a class="button" href="">Cancel</a>
</div>

.button { display: inline-block; margin-right: 16px; /* Other button styles */
}

Вы определили, что интервал равен 16px, но если вы измеряете его в браузере, он больше. Если вы торопитесь, вы можете просто уменьшить поде и сделать его 10px в CSS, а в браузере оно станет 16px. Если вам повезет, дизайнер может не заметить, что вы здесь сделали, но это плохое решение.

Это происходит потому, что кнопки являются встроенными элементами, и браузер обрабатывает их как текстовые символы. Между текстовыми символами есть интервал. Прямого способа исправить это нет, и большинство решений — это хаки.

Если я хочу решить эту проблему, я сделаю родительскую оболочку кнопок флекс-контейнером, и тогда интервал будет работать, как ожидалось, без каких-либо хаков.

.wrapper { display: flex; flex-wrap: wrap;
} .button { margin-right: 16px; /* Other button styles */
}

Заключение

Для вас как для фронт-энд разработчика важно найти первопричину ошибки в CSS. Вот что вы получите, решив проблему с нуля:

Вы узнаете что-то новое.

Вы никогда не забудете решение.

Вы станете более опытным.

Это весело.

Автор: Ahmad Shadeed

Источник: ishadeed.com

Редакция: Команда webformyself.