Select Methods
The following are the most common methods used on Selenium dropdown list.
Method | Description |
---|---|
selectByVisibleText() anddeselectByVisibleText()
Example: |
|
selectByValue() anddeselectByValue()
Example: |
|
selectByIndex() and deselectByIndex()
Example: |
|
isMultiple()
Example: |
|
deselectAll()
Example: |
|
Using Reactive Form
1.1. Dynamically Set Value using FormGroup.setValue
user-reactive.component.ts
@Component({ selector: 'app-reactive', templateUrl: './user-reactive.component.html', styleUrls: ['./user.component.css'] }) export class UserReactiveComponent implements OnInit { isValidFormSubmitted = false; allProfiles: Profile[]; allTechnologies: Technology[]; userForm: FormGroup; constructor(private formBuilder: FormBuilder, private userService: UserService) { } ngOnInit(): void { this.userForm = this.formBuilder.group({ profile: ], userName: ], technologies: ] }); this.allProfiles = this.userService.getPofiles(); this.allTechnologies = this.userService.getTechnologies(); } setDefaultValues() { let user = new User(); user.userName = "Narendra Modi"; user.profile = this.allProfiles; user.technologies = , this.allTechnologies ]; this.userForm.setValue(user); } ------ }
user-reactive.component.html
<select formControlName="profile"> <option ="null" disabled>Choose your profile</option> <option *ngFor="let prf of allProfiles" ="prf"> ` prf`.`prName ` </option> </select> <select multiple formControlName="technologies" ="compareTech"> <option *ngFor="let tech of allTechnologies" ="tech"> ` tech`.`techName ` </option> </select> <button type="button" (click)="setDefaultValues()">Set Default</button>
1.2. Dynamically Set Value using FormGroup.patchValue
setDefaultValues() { let userProfile = this.allProfiles; let userTechnologies = , this.allTechnologies ]; this.userForm.patchValue({profile:userProfile, technologies:userTechnologies}); }
1.4. Set Default Value with ‘selected’ Attribute
<select formControlName="profile" (change)="onProfileChange()"> <option ="null" disabled>Choose your profile</option> <option *ngFor="let prf of allProfiles" ="prf" ="prf.prId==='dir'"> ` prf`.`prName ` </option> </select>
База данных для примеров
Дальше будет много примеров и логично постоянно использовать одну и ту же БД, что бы не рисовать каждый раз новые. На основании базы данных ниже будут продемонстрированы все примеры, не только в этой статье, но и в других.
Постановка задачи: пусть требуется разработать БД для предметной области «Поставка деталей»!
Требуется хранить следующую информацию:
- О поставщиках (P) pnum, pname
- О деталях (D) pnum, dname, dprice
- О поставках (PD) volume
Значения таблицы P:
pnum | pname |
---|---|
1 | Иванов |
2 | Петров |
3 | Сидоров |
4 | Кузнецов |
Значения таблицы D:
pnum | dname | dprice |
---|---|---|
1 | Болт | 10 |
2 | Гайка | 20 |
3 | Винт | 30 |
Значения таблицы PD:
pnum | dnum | volume |
---|---|---|
1 | 1 | 100 |
1 | 2 | 100 |
1 | 3 | 300 |
2 | 1 | 150 |
1 | 2 | 250 |
3 | 1 | 1000 |
Как настроить стрелку для select
Часто, стрелка (индикатор того, что это выпадашка — поле выбора значений) по умолчанию плохо вписывается в дизайн и её лучше заменить на что-нибудь более подходящее. Вот необходимый минимум стилей, с помощью которых можно заменить стрелку у :
Здесь удаляются стили, устанавливаемые браузером, освобождается место для графической стрелки, а затем новая картинка стрелки вставляется в качестве фона. Это должно применяться только в том случае, если обычный и предназначен для выбора одиночного значения, а не нескольких ().
See this code Select с измененной стрелкой on x.xhtml.ru.
Этот пример демонстрирует замену стрелки по умолчанию элементу .
Предложение ORDER BY
При выполнении запроса СУБД возвращает строки в случайном порядке. Предложение позволяет упорядочить выходные данные запроса в соответствии со значениями одного или нескольких выбранных столбцов.
Можно задать возрастающий — (от слова Ascend) или убывающий — (от слова Descend) порядок сортировки. По умолчанию принят возрастающий порядок сортировки.
Пример 22.Отсортировать таблицу PD в порядке возрастания номеров поставщиков, а строки с одинаковыми значениями pnum отсортировать в порядке убывания объема поставок.
pnum | volume | dnum |
---|---|---|
1 | 300 | 3 |
1 | 200 | 2 |
1 | 100 | 1 |
2 | 250 | 2 |
2 | 150 | 1 |
3 | 1000 | 1 |
Операцию удобно применять после сортировки результирующего набора с помощью предложения .
Пример 24.Определить номера первых двух деталей с наименьшей стоимостью.
Следует отметить, что если в таблице D будут две детали без указания цены, то именно их и отобразит предыдущий запрос.
Поэтому при наличии -значений их необходимо исключать с помощью предложения WHERE.
Дополнительно о SELECT
Теперь, когда мы научились делать простые запросы с и , можно ненадолго снова вернуться к .
Агрегатные функции
В операторе можно использовать агрегатные функции, которые дают единственное значение для целой группы строк в таблице.
Агрегатная функция записывается в следующем виде:
Пользователю доступны следующие агрегатные функции:
- ‑ вычисляет сумму множества значений указанного столбца;
- ‑ вычисляет количество значений указанного столбца;
- / ‑ определяет минимальное/максимальное значение в указанном столбце;
- ‑ вычисляет среднее арифметическое значение множества значений столбца;
- / ‑ определяет первое/последнее значение в указанном столбце.
Пример 15.Определить общий объем поставляемых деталей.
Expr1000 |
---|
2000 |
Вычисляемые столбцы
Столбцы результирующей таблицы, которых не существовало в исходных таблицах, называются вычисляемыми. Таким столбцам СУБД присваивает системные имена, что не всегда является удобным.
При вычислении результатов любой агрегатной функции СУБД сначала исключает все -значения, после чего требуемая операция применяется к оставшимся значениям.
Для функции возможен особый вариант использования — . Его назначение состоит в подсчете всех строк в результирующей таблице, включая -значения.
Следует запомнить, что агрегатные функции нельзя вкладывать друг в друга. Такая конструкция работать не будет: `MAX(SUM(VOLUME))`
Переименование столбца
Язык SQL позволяет задавать новые имена столбцам результирующей таблицы, для чего используется операция . Переименование также используют для изменения сложных имен столбцов таблицы.
Например, присвоить новое имя вычисляемому столбцу в предыдущем примере позволит выполнение следующего запроса.
Sum |
---|
2000 |
Пример 16.Определить количество поставщиков, которые поставляют детали в настоящее время.
Count |
---|
6 |
Несмотря на то, что реальное число поставщиков деталей в таблице PD равно 3, СУБД возвращает число 6
Такой результат объясняется тем, что СУБД подсчитывает все строки в таблице PD, не обращая внимание на то, что в строках есть одинаковые значения
Операция
Если до применения агрегатной функции необходимо исключить дублирующиеся значения, следует перед именем столбца указать ключевое слово .
Count |
---|
3 |
можно задать только один раз для одного предложения .
Противоположностью является операция . Она имеет противоположное действие «показать все строки таблицы» и предполагается по умолчанию.
Предложение WHERE
После служебного слова указываются условия выбора строк, помещаемых в результирующую таблицу. Существуют различные типы условий выбора:
Типы условий выбора:
- Сравнение значений атрибутов со скалярными выражениями, другими атрибутами или результатами вычисления выражений.
- Проверка значения на принадлежность множеству.
- Проверка значения на принадлежность диапазону.
- Проверка строкового значения на соответствие шаблону.
- Проверка на наличие null-значения.
Сравнение
В языке SQL используются традиционные операции сравнения ,,,,,.
В качестве условия в предложении можно использовать сложные логические выражения, использующие атрибуты таблиц, константы, скобки, операции , , отрицание .
Пример 5.Определить номера деталей, поставляемых поставщиком с номером 2.
Пример 6.Получить информацию о поставщиках Иванов и Петров.
Строковые значения атрибутов заключаются в апострофы.
Проверка на принадлежность множеству
Операция проверяет, принадлежит ли значение атрибута заданному множеству.
Пример 7.Получить информацию о поставщиках ‘Иванов’ и ‘Петров’.
Пример 8.Получить информацию о деталях с номерами 1 и 2.
Проверка на принадлежность диапазону
Операция определяет минимальную и максимальную границу диапазона, в которое должно попадать значение атрибута. Обе границы считаются принадлежащими диапазону.
Пример 9.Определить номера деталей, с ценой от 10 до 20 рублей.
Пример 10.Вывести наименования поставщиков, начинающихся с букв от ‘К’ по ‘П’.
Сравнение символов
Буква ‘Р’ в условии запроса объясняется тем, что строки сравниваются посимвольно. Для каждого символа при этом определяется код. Для нашего случая справедливо условие: ‘П’<‘Петров’<‘Р’
Проверка строкового значения на соответствие шаблону
Операция используется для поиска подстрок. Значения столбца, указываемого перед служебным словом сравниваются с задаваемым после него шаблоном. Форматы шаблонов различаются в конкретных СУБД.
Для СУБД MS SQL Server:
- Символ заменяет любое количество любых символов.
- Символ заменяет один любой символ.
- ‑ вместо символа строки может быть подставлен один любой символ из множества возможных, указанных в ограничителях.
- ‑ вместо символа строки может быть подставлен любой из символов кроме символов из множества, указанного в ограничителях.
Множество символов в квадратных скобках можно указывать через запятую, либо в виде диапазона.
Пример 11.Вывести фамилии поставщиков, начинающихся с буквы ‘И’.
Пример 12.Вывести фамилии поставщиков, начинающихся с букв от ‘К’ по ‘П’.
Проверка на наличие null-значения
Операции и используются для сравнения значения атрибута со значением .
Пример 13.Определить наименования деталей, для которых не указана цена.
Пример 14.Определить номера поставщиков, для которых указано наименование.
Включение и отключение кнопки на чистом JavaScript
В этом разделе мы разберем пример кода на чистом JavaScript, который активирует и отключает кнопку. Посмотрите на приведенный ниже фрагмент кода:
<html> <head> <script> function toggleButton() { var username = document.getElementById('username').value; var password = document.getElementById('password').value; if (username && password) { document.getElementById('submitButton').disabled = false; } else { document.getElementById('submitButton').disabled = true; } } </script> </head> <body> <div> <form action="/submit.php" method="post"> Username:<input type="text" name="username" id="username" onchange="toggleButton()"> Password:<input type="password" name="password" id="password" onchange="toggleButton()"> <input id="submitButton" type="submit" value="Submit" disabled/> </form> </div> </body> </html>
Данный код создает простейшую форму с двумя полями для ввода текста и кнопкой для отправки введенных данных на сервер
Важно отметить, что во время загрузки страницы кнопка формы находится в отключенном состоянии – для этого в коде по умолчанию используется свойство disabled
После загрузки формы в коде предусмотрено событие onchange, связанное с изменением состояния текстовых полей для ввода имени и пароля пользователя. Как только пользователь введет какие-либо данные в любое из этих полей, событие onchange сработает, и вызовет функцию включения и отключения кнопки toggleButton.
Функция toggleButton проверяет, ввел ли пользователь данные в оба обязательных поля. Если пользователь ввел имя и пароль, функция изменит состояние disabled на false, что в итоге приведет к активации кнопки отправки введенных данных. Если же одно из обязательных полей осталось незаполненным, свойство disabled получает параметр true, и как следствие этого, кнопка остается неактивной.
В приведенном выше примере для создания кнопки используется элемент <input>, но при желании также можно использовать HTML-кнопку <button>, как показано ниже:
<button id="submitButton" disabled/>Submit</button>
Вот так и выглядит активация и отключение кнопки на чистом JavaScript. В следующем разделе мы рассмотрим, как включать и отключать кнопки при работе с библиотекой jQuery.
Основные стили
Сперва сбросим параметры текста.
Свойство наследует все стили от контейнера(ов). Иногда при сбросе CSS указывают размер шрифта , но в этом нет необходимости. будет наследовать стили всех своих параметров: , , , , , и (если установлено). Ещё он добавляет высоту строки . В-общем, шрифт будет адаптироваться к изменениям, которые касаются всей страницы, либо с помощью надстроек, либо через настройки браузера/системы.
Если пользователь (или автор) изменяет параметры текста, чтобы повлиять на расстояние между буквами, это не будет касаться предустановленных для поля значений. Наследование параметров не повлияет на межбуквенное расстояние, поэтому нужно явно указать необходимость наследования значения . Это поможет соответствовать требованиям
Аналогично межбуквенному , значение для управления интервалами между словами не будет наследоваться, если это не объявить явным образом. WCAG 1.4.12 применяется и для расстояния между словами.
Обратите внимание, что в коде не устанавливается высота строки. Это значение нормально наследуется вместе с остальными параметрами шрифта в свойстве
Если обнаружится, что это не так (например, из-за явной установки высоты строки ) можно добавить , чтобы соответствовать WCAG 1.4.12.
Пример
В этом примере демонстрируется применение этого минимального набора стилей.
See this code Простой Select on x.xhtml.ru.
Select Option from Drop-Down Box
Following is a step by step process on how to select value from dropdown in Selenium:
Before handling dropdown in Selenium and controlling drop-down boxes, we must do following two things:
- Import the package org.openqa.selenium.support.ui.Select
- Instantiate the drop-down box as an object, Select in Selenium WebDriver
As an example, go to Mercury Tours’ Registration page () and notice the “Country” drop-down box there.
Step 1
Import the “Select” package.
Step 2
Declare the drop-down element as an instance of the Select class. In the example below, we named this instance as “drpCountry”.
Step 3
We can now start controlling “drpCountry” by using any of the available Select methods to select dropdown in Selenium. The sample code below will select the option “ANTARCTICA.”
Подход на основе элементов details и summary
В HTML существуют элементы details и summary, которые позволяют создать панель расширения:
<details> <summary>Click to open/close</summary> Here is the content that is revealed when clicking the summary... </details>
Кроме этого элемент details поддерживает JavaScript-событие toggle. Поэтому можно изменять HTML в зависимости от того, скрыто или отображается содержимое панели.
details.addEventListener("toggle", () => { details.open ? thisCoolThing() : thisOtherThing(); })
Но элементы details и summary не анимируются и к ним нельзя применять переходы. Поэтому используем другие средства.
Select Options in Template Driven Forms
The following is the code for the select options in Template Driven Forms. Also refer to the tutorial on how to set value in template driven forms.
We get the reference to the using the .
Use the to wait for a change detection cycle so that the updates the reference to the . Without it the will return null.
To Listen to the change we use the using the . We can also use the
Rest of the code is very similar to the Reactive forms.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
import{Component,ViewChild,OnInit}from’@angular/core’; import{NgForm,FormGroup,FormControl,FormBuilder}from’@angular/forms’; @Component({ selector’app-root’, templateUrl’./app.component.html’, styleUrls’./app.component.css’ }) exportclassAppComponentimplementsOnInit{ title=’Angular Select Options Example’; @ViewChild(«contactForm»,null)contactFormNgForm; constructor(privatefbFormBuilder){ } country_name=»»; set_country=»»; countries= {id1,name»United States»}, {id2,name»Australia»}, {id3,name»Canada»}, {id4,name»Brazil»}, {id5,name»England»} ; ngOnInit(){ setTimeout(()=>{ this.setDefaults(); }) } submit(){ console.log(«Form Submitted») console.log(this.contactForm.value) } setDefaults(){ this.contactForm.form.get(«country»).patchValue(null); } onCountryChanged(value){ console.log(‘onCountryChanged’) console.log(value) } addCountry(){ constcountry=this.countries.find(el=>el.name===this.country_name); if(!country){ let id=Math.max.apply(Math,this.countries.map(function(o){returno.id;})) this.countries.push({idid+1,namethis.country_name}) this.country_name=»»; } } setCountry(){ constcountry=this.countries.find(el=>el.name===this.set_country); if(country){ this.contactForm.form.get(«country»).patchValue(country.id); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<h1>Angular Select Option Example</h1> <form#contactForm=»ngForm» (ngSubmit)=»submit()»> <p> <select name=»country»ngModel(ngModelChange)=»onCountryChanged($event)»> <optionngValue=»null»disabled>Select Country</option> <option*ngFor=»let country of countries»ngValue=»country.id»>{{country.name}}</option> </select> <button type=»submit»>Submit</button> </p> </form> <p> <input(ngModel)=»country_name»> <button(click)=»addCountry()»>Add</button> </p> <p> <input(ngModel)=»set_country»> <button(click)=»setCountry()»>SetCountry</button> </p>
|
Dynamically Set Value using ngModel in Template-Driven Form
user-templatedriven.component.ts
@Component({ selector: 'app-template', templateUrl: './user-templatedriven.component.html', styleUrls: ['./user.component.css'] }) export class UserTemplateDrivenComponent implements OnInit { allProfiles: Profile[]; allTechnologies: Technology[]; user = new User(); constructor(private userService: UserService) { } ngOnInit(): void { this.allProfiles = this.userService.getPofiles(); this.allTechnologies = this.userService.getTechnologies(); } setDefaultValues() { this.user.userName = "Narendra Modi"; this.user.profile = this.allProfiles; this.user.technologies = , this.allTechnologies ]; } ------ }
user-templatedriven.component.html
<select name="profile" ="user.profile"> <option ="null" disabled>Choose your profile</option> <option *ngFor="let prf of allProfiles" ="prf"> ` prf`.`prName ` </option> </select> <select multiple name="selectedTechs" ="compareTech" ="user.technologies"> <option *ngFor="let tech of allTechnologies" ="tech"> ` tech`.`techName ` </option> </select> <button type="button" (click)="setDefaultValues()">Set Default</button>
user-service.ts
import { Injectable } from '@angular/core'; import { Profile } from '../domain/profile'; import { Technology } from '../domain/technology'; import { User } from '../domain/user'; @Injectable({ providedIn: 'root' }) export class UserService { getPofiles(): Profile[] { let profiles = return profiles; } getTechnologies(): Technology[] { let technologies = return technologies; } createUser(user: User) { //Log user data in console console.log("User Name: " + user.userName); console.log("Profile Id: " + user.profile.prId); console.log("Profile Name: " + user.profile.prName); for (let i = 0; i < user.technologies.length; i++) { console.log("Technology Id: " + user.technologies.techId); console.log("Technology Name: " + user.technologies.techName); } } }
References
Angular Select Option + Multiple Select Option + Validation Example using Template-Driven FormAngular Select Option using Reactive Form
Продолжение настройки select
Стоит обратить внимание, что интервалы у текста не очень хороши. Потенциально можно сделать их более привлекательными, удобными и доступными для пользователей с помощью всего нескольких дополнительных стилей
Например, можно настроить и . Эти два свойства расширяют базовые стили, описанные выше, чтобы сделать текстовые поля более удобными.
Изменение значений CSS-свойств для рамки поля сопряжено с риском. Согласно WCAG (), если для элемента формы не вносить изменений в стили по умолчанию, то это никак не повлияет на контрастность. Тем не менее, с помощью будет установлена толщина рамки на основе размера шрифта. Теперь рамка поля выбора будет масштабироваться вместе с текстом. Заодно она становится толще, чем используется по умолчанию в большинстве браузеров.
Здесь умышленно не установлен цвет рамки, чтобы позволить браузеру сделать это самостоятельно. Конечно, если фон страницы не белый, можно изменить цвет рамки.
Трогать для не обязательно. Однако, содержимое поля будет немного легче читать и использовать, если немного его настроить. Это поможет сделать отступы в ближе к аналогичным в и , если их тоже предстоит настраивать.
Here is the complete code
package newpackage; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.support.ui.Select; import org.openqa.selenium.By; public class accessDropDown { public static void main(String[] args) { System.setProperty("webdriver.gecko.driver","C:\\geckodriver.exe"); String baseURL = "http://demo.guru99.com/test/newtours/register.php"; WebDriver driver = new FirefoxDriver(); driver.get(baseURL); Select drpCountry = new Select(driver.findElement(By.name("country"))); drpCountry.selectByVisibleText("ANTARCTICA"); //Selecting Items in a Multiple SELECT elements driver.get("http://jsbin.com/osebed/2"); Select fruits = new Select(driver.findElement(By.id("fruits"))); fruits.selectByVisibleText("Banana"); fruits.selectByIndex(1); } }
Базовая логика
- После загрузки веб-страницы измеряем высоту содержимого.
- Устанавливаем высоту содержимого в контейнере в качестве значения пользовательского свойства CSS.
- Скрываем содержимое, добавив к нему атрибут aria-hidden: «true».
- Устанавливаем max-height в качестве значения пользовательского свойства.
- Нажатие кнопки изменяет значение свойства aria-hidden с true на false. А также max-height содержимого с 0 на высоту, заданную в пользовательском свойстве. Затем с помощью переходов реализуем визуальный эффект.
JavaScript-код
// Получаем контейнер const container = document.querySelector(".container"); // Получаем контент: const content = document.querySelector(".content"); // 1. Получаем высоту контента, который мы хотим показать/скрыть const heightOfContent = content.getBoundingClientRect().height; // Получаем кнопку const btn = document.querySelector(".trigger"); // 2. Задаем пользовательские свойства CSS с высотой контента container.style.setProperty("--containerHeight", `${heightOfContent}px`); // Когда высота задана setTimeout(e => { document.documentElement.classList.add("height-is-set"); 3. content.setAttribute("aria-hidden", "true"); }, 0); btn.addEventListener("click", function(e) { container.setAttribute("data-drawer-showing", container.getAttribute("data-drawer-showing") === "true" ? "false" : "true"); // 5. Переключаем значение aria-hidden content.setAttribute("aria-hidden", content.getAttribute("aria-hidden") === "true" ? "false" : "true"); })
CSS
.content { transition: max-height 0.2s; overflow: hidden; } .content { max-height: 0; } // 4. Задаем для высоты значение пользовательского свойства .content { max-height: var(--containerHeight, 1000px); }
Все вместе
Полная версия JavaScript-кода примера:
var containers; function initDrawers() { // Получаем контейнер с контентом containers = document.querySelectorAll(".container"); setHeights(); wireUpTriggers(); window.addEventListener("resize", setHeights); } window.addEventListener("load", initDrawers); function setHeights() { containers.forEach(container => { // Получаем контент let content = container.querySelector(".content"); content.removeAttribute("aria-hidden"); // Высота контента, который нужно скрыть/показать let heightOfContent = content.getBoundingClientRect().height; // Задаем пользовательские свойства CSS с высотой контента container.style.setProperty("--containerHeight", `${heightOfContent}px`); // Когда высота считана и задана setTimeout(e => { container.classList.add("height-is-set"); content.setAttribute("aria-hidden", "true"); }, 0); }); } function wireUpTriggers() { containers.forEach(container => { // Получаем все элементы-триггеры let btn = container.querySelector(".trigger"); // Получаем контент let content = container.querySelector(".content"); btn.addEventListener("click", () => { btn.setAttribute("aria-expanded", btn.getAttribute("aria-expanded") === "false" ? "true" : "false"); container.setAttribute( "data-drawer-showing", container.getAttribute("data-drawer-showing") === "true" ? "false" : "true" ); content.setAttribute( "aria-hidden", content.getAttribute("aria-hidden") === "true" ? "false" : "true" ); }); }); }
Вы также можете поэкспериментировать с кодом, размещенным на CodePen
Какой из подходов лучше?
С точки зрения производительности использование transform более эффективно, чем анимация height и max-height. При применении CSS-свойства transform элементы растризуются и перемещаются графическим процессором. Это низко затратная и простая операция для графического процессора.
Для реализации данного подхода нужно выполнить следующие действия:
- Получить высоту контента, который будет располагаться на панели.
- Переместить контент выше на высоту содержимого, которое будет свернуто с помощью transform: translateY(Xpx). С помощью перехода реализовать эффект открытия и закрытия панели.
- С помощью JavaScript перехватить событие transitionend. После его наступления задаем display: none для контента и удаляем преобразование.
Но у данного метода есть множество недостатков. Например, при использовании transform: translateY необходимо учитывать z-index элемента.
Поэтому проще с помощью JavaScript обернуть все, что вы хотите переместить, в контейнер и переместить его. Вот пример использования данного подхода.
Применение переходов к max-height работает не так хорошо, как свойство transform. Так как браузер изменяет высоту сворачивающегося элемента на протяжении всего перехода. Эта операция потребляет много ресурсов памяти и графического процессора. Но зато данный подход проще в реализации.
Заключение
Пример стилизованного в разных состояниях с сохранением WCAG-доступности.
See this code Select Menus on x.xhtml.ru.
Когда речь идет о стилизации полей формы, нужно обратить внимание на минимальный набор стилей, который понадобится, чтобы обеспечить соответствие общему дизайну и поддержку состояний, которые перечислены выше. Похожие публикации, посвященные стилизации HTML-элемента : Select Like It’s 2019 и Custom Select Styles with Pure CSS немного отличаются подходами, но заслуживают не меньшего внимания
Может быть эти варианты даже лучше соответствуют вашим целям и требованиям
Похожие публикации, посвященные стилизации HTML-элемента : Select Like It’s 2019 и Custom Select Styles with Pure CSS немного отличаются подходами, но заслуживают не меньшего внимания. Может быть эти варианты даже лучше соответствуют вашим целям и требованиям.