Добавить элемент в правило Less CSS

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

Использование & после того, как правила были определены, добавляет тип элемента в конец правила, и с пробелом или без него это явно не работает.

Я уверен, что есть менее повторяющийся, более оптимальный способ написать следующее:

&.admin {
    .service_provider.security_class_admin,
    .service_provider.security_class_admin_manager,
    .service_provider.security_class_admin_user,
    .service_provider.security_class_admin_manager_user {
        display: block;
    }
    th {
        &.service_provider.security_class_admin,
        &.service_provider.security_class_admin_manager,
        &.service_provider.security_class_admin_user,
        &.service_provider.security_class_admin_manager_user {
            display: table-cell;
        }
    }
    button {
        &.service_provider.security_class_admin,
        &.service_provider.security_class_admin_manager,
        &.service_provider.security_class_admin_user,
        &.service_provider.security_class_admin_manager_user {
            display: inline-block;
        }
    }
}

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


person user2115620    schedule 13.06.2016    source источник


Ответы (2)


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

Вы можете написать миксин так, чтобы он имел все общие селекторы и принимал набор правил в качестве входных данных.

&.admin{
    .common-selectors({display: block;});
    th{
        .common-selectors({display: table-cell;}, append);
    }
    button{
        .common-selectors({display: inline-block;}, append);
    }
}

.common-selectors(@props, @type:child){
    & when (@type = append) { /* type check because the element type is appended */
        &.service_provider.security_class_admin,
        &.service_provider.security_class_admin_manager,
        &.service_provider.security_class_admin_user,
        &.service_provider.security_class_admin_manager_user{
            @props();
        }
    }
    & when not (@type = append) { /* type check because default shouldn't be appended */
        .service_provider.security_class_admin,
        .service_provider.security_class_admin_manager,
        .service_provider.security_class_admin_user,
        .service_provider.security_class_admin_manager_user{
            @props();
        }
    }    
}

Фрагмент на основе скомпилированного вывода приведенного выше кода:

.admin .service_provider.security_class_admin,
.admin .service_provider.security_class_admin_manager,
.admin .service_provider.security_class_admin_user,
.admin .service_provider.security_class_admin_manager_user {
  display: block;
}
.admin th.service_provider.security_class_admin,
.admin th.service_provider.security_class_admin_manager,
.admin th.service_provider.security_class_admin_user,
.admin th.service_provider.security_class_admin_manager_user {
  display: table-cell;
}
.admin button.service_provider.security_class_admin,
.admin button.service_provider.security_class_admin_manager,
.admin button.service_provider.security_class_admin_user,
.admin button.service_provider.security_class_admin_manager_user {
  display: inline-block;
}
div,
span,
button,
th,
tr,
table {
  border: 1px solid;
  margin: 10px;
}
<div class='admin'>
  <div class='service_provider security_class_admin'>Admin</div>
  <div class='service_provider security_class_admin_manager'>Manager</div>
  <div class='service_provider security_class_admin_user'>User</div>
  <div class='service_provider security_class_admin_manager_user'>Manager User</div>
</div>
<div class='admin'>
  <span class='service_provider security_class_admin'>Admin</span>
  <span class='service_provider security_class_admin_manager'>Manager</span>
  <span class='service_provider security_class_admin_user'>User</span>
  <span class='service_provider security_class_admin_manager_user'>Manager User</span>
</div>
<div class='admin'>
  <button class='service_provider security_class_admin'>Admin</button>
  <button class='service_provider security_class_admin_manager'>Manager</button>
  <button class='service_provider security_class_admin_user'>User</button>
  <button class='service_provider security_class_admin_manager_user'>Manager User</button>
</div>
<table>
  <tr>
    <th class='service_provider security_class_admin'>Admin</th>
    <th class='service_provider security_class_admin_manager'>Manager</th>
    <th class='service_provider security_class_admin_user'>User</th>
    <th class='service_provider security_class_admin_manager_user'>Manager User</th>
  </tr>
</table>


Или более короткий подход для примесей — использовать универсальный селектор (*) для блокировки отображения всех элементов.

&.admin{
    * {
        .common-selectors({display: block;});
    }
    th{
        .common-selectors({display: table-cell;});
    }
    button{
        .common-selectors({display: inline-block;});
    }
}

.common-selectors(@props, @type:child){
    &.service_provider.security_class_admin,
    &.service_provider.security_class_admin_manager,
    &.service_provider.security_class_admin_user,
    &.service_provider.security_class_admin_manager_user{
        @props();
    }
}

Фрагмент на основе скомпилированного вывода приведенного выше кода:

.admin *.service_provider.security_class_admin,
.admin *.service_provider.security_class_admin_manager,
.admin *.service_provider.security_class_admin_user,
.admin *.service_provider.security_class_admin_manager_user {
  display: block;
}
.admin th.service_provider.security_class_admin,
.admin th.service_provider.security_class_admin_manager,
.admin th.service_provider.security_class_admin_user,
.admin th.service_provider.security_class_admin_manager_user {
  display: table-cell;
}
.admin button.service_provider.security_class_admin,
.admin button.service_provider.security_class_admin_manager,
.admin button.service_provider.security_class_admin_user,
.admin button.service_provider.security_class_admin_manager_user {
  display: inline-block;
}
div,
span,
button,
th,
tr,
table {
  border: 1px solid;
  margin: 10px;
}
<div class='admin'>
  <div class='service_provider security_class_admin'>Admin</div>
  <div class='service_provider security_class_admin_manager'>Manager</div>
  <div class='service_provider security_class_admin_user'>User</div>
  <div class='service_provider security_class_admin_manager_user'>Manager User</div>
</div>
<div class='admin'>
  <span class='service_provider security_class_admin'>Admin</span>
  <span class='service_provider security_class_admin_manager'>Manager</span>
  <span class='service_provider security_class_admin_user'>User</span>
  <span class='service_provider security_class_admin_manager_user'>Manager User</span>
</div>
<div class='admin'>
  <button class='service_provider security_class_admin'>Admin</button>
  <button class='service_provider security_class_admin_manager'>Manager</button>
  <button class='service_provider security_class_admin_user'>User</button>
  <button class='service_provider security_class_admin_manager_user'>Manager User</button>
</div>
<table>
  <tr>
    <th class='service_provider security_class_admin'>Admin</th>
    <th class='service_provider security_class_admin_manager'>Manager</th>
    <th class='service_provider security_class_admin_user'>User</th>
    <th class='service_provider security_class_admin_manager_user'>Manager User</th>
  </tr>
</table>

person Harry    schedule 13.06.2016
comment
хороший, спасибо Гарри, это, безусловно, поможет оптимизировать вещи. - person user2115620; 13.06.2016
comment
Это нормально. Сейчас я учусь МЕНЬШЕ, и это хорошее решение. Использование миксинов действительно помогает - person Marcos Pérez Gude; 13.06.2016
comment
@user2115620: user2115620: На самом деле я сделал ошибку, из-за которой вывод исходного миксина не был бы таким же, как ваш код. Я изменил его сейчас, пожалуйста, обратите внимание. Это связано с тем, что общие селекторы работают двумя способами. Когда они вложены в типы элементов, они должны быть добавлены к родителю, тогда как в том, что находится вне селектора типа элемента, этого не должно быть. Значит, нужен еще один уровень проверки. - person Harry; 13.06.2016
comment
Это when () заявление было мне неизвестно. Спасибо за поправку :) - person Marcos Pérez Gude; 13.06.2016
comment
@MarcosPérezGude: это похоже на конструкцию if. Проверьте значение переменной, а затем решите, должно ли выполняться содержимое или нет :) - person Harry; 13.06.2016

Итак, благодаря вашей помощи, а также циклу for-in, о котором я узнал из следующего сообщения: Как сгенерировать CSS с циклом в less

Теперь у меня есть:

.for(@list, @code) {
        & {
            .loop(@i:1) when (@i =< length(@list)) {
                @value: extract(@list, @i);

                @code();

                .loop(@i + 1);
            }

            .loop();
        }
    }

    .role-varients(@orgType, @variants, @props, @type:child){
        .for(@variants, {
            & when (@type = append) {
                &.@{orgType}.security_class_@{value} {
                    @props();
                }
            }
            & when not (@type = append) {
                .@{orgType}.security_class_@{value} {
                    @props();
                }
            }
        });
    }
    @admin-roles: admin, admin_manager, admin_user, admin_manager_user;
    @manager-roles: manager, admin_manager, manager_user, admin_manager_user;
    @user-roles: user, admin_user, manager_user, admin_manager_user;
    &.service_provider{
        &.admin{
            .role-varients(service_provider, @admin-roles, {display: block;});
            th{
                .role-varients(service_provider, @admin-roles, {display: table-cell;}, append);
            }
            button{
                .role-varients(service_provider, @admin-roles, {display: inline-block;}, append);
            }
        }
        &.manager{
            .role-varients(service_provider, @manager-roles, {display: block;});
            th{
                .role-varients(service_provider, @manager-roles, {display: table-cell;}, append);
            }
            button{
                .role-varients(service_provider, @manager-roles, {display: inline-block;}, append);
            }
        }
        &.user{
            .role-varients(service_provider, @user-roles, {display: block;});
            th{
                .role-varients(service_provider, @user-roles, {display: table-cell;}, append);
            }
            button{
                .role-varients(service_provider, @user-roles, {display: inline-block;}, append);
            }
        }
    }
    &.client{
        &.admin{
            .role-varients(client, @admin-roles, {display: block;});
            th{
                .role-varients(client, @admin-roles, {display: table-cell;}, append);
            }
            button{
                .role-varients(client, @admin-roles, {display: inline-block;}, append);
            }
        }
        &.manager{
            .role-varients(client, @manager-roles, {display: block;});
            th{
                .role-varients(client, @manager-roles, {display: table-cell;}, append);
            }
            button{
                .role-varients(client, @manager-roles, {display: inline-block;}, append);
            }
        }
        &.user{
            .role-varients(client, @user-roles, {display: block;});
            th{
                .role-varients(client, @user-roles, {display: table-cell;}, append);
            }
            button{
                .role-varients(client, @user-roles, {display: inline-block;}, append);
            }
        }
    }
    &.vendor{
        &.admin{
            .role-varients(vendor, @admin-roles, {display: block;});
            th{
                .role-varients(vendor, @admin-roles, {display: table-cell;}, append);
            }
            button{
                .role-varients(vendor, @admin-roles, {display: inline-block;}, append);
            }
        }
        &.manager{
            .role-varients(vendor, @manager-roles, {display: block;});
            th{
                .role-varients(vendor, @manager-roles, {display: table-cell;}, append);
            }
            button{
                .role-varients(vendor, @manager-roles, {display: inline-block;}, append);
            }
        }

        &.user{
            .role-varients(vendor, @user-roles, {display: block;});
            th{
                .role-varients(vendor, @user-roles, {display: table-cell;}, append);
            }
            button{
                .role-varients(vendor, @user-roles, {display: inline-block;}, append);
            }
        }
    }

Я бы использовал другой цикл for для обработки 3 основных блоков [service_provider, client, vendor], но там, где я использую .@{value}, я предполагаю, что область действия нарушена из-за наличия цикла внутри цикла, и он не дает ожидаемых результатов. .

Хотя приведенное выше все еще кажется длинным, это определенно лучше, чем писать каждое правило вручную.

Мое решение появилось благодаря вкладу Гарри, поэтому, наверное, мне следует отметить его ответ как правильный? Всем еще раз спасибо ;)

person user2115620    schedule 13.06.2016
comment
Отметка о принятии - это полностью ваш выбор, но общее правило состоит в том, чтобы принять ответ, который полностью касался исходного вопроса. Любые дополнительные материалы, которые вы сделали для улучшения этого ответа, могут быть опубликованы, поскольку они могут быть полезны другим. Если другой ответ был частичным, а ваш ответ является полным на исходный вопрос, вы принимаете свой :) - person Harry; 13.06.2016
comment
спасибо за руководство, Гарри - ваш ответ решил для меня первоначальную проблему, я только что построил ее;) - person user2115620; 14.06.2016