Less.js: Родительские селекторы должны иметь цели

Созданный на 13 дек. 2012  ·  118Комментарии  ·  Источник: less/less.js

При создании правила родительского селектора все до & добавляется в начало самой внешней области.

Эту функцию можно значительно улучшить, разрешив «нацеливание на родительский объект», где вы можете применить родительский селектор к определенному родителю (в случае, если у вас есть глубоко вложенные селекторы).

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

feature request medium priority needs decision

Самый полезный комментарий

Я собираюсь снова открыть это. Мы видели вариации этой идеи (например, #1154), и я чувствую, что есть возможность решения.

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

Кроме того, бывают случаи, когда люди хотят унаследовать НЕКОТОРЫЕ части стека, но не все.

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

.main-content {
    .button {
        .button-icon {
            background-image: @button-icon;
            &{2}:hover { background-image: @button-icon-hover; }
            &{2}.focus { background-image: @button-icon-focus; }
            .ie8 &{3} { background-image: @button-icon-ie8; }  // In this case, &{3} is the same as & because it goes to top
        }
    }
}

По сути, шагните «вверх» по дереву наследования до уровня, который мы хотим наследовать/добавить к текущим селекторам.

Или что-то вроде «нарушения» наследования и начала заново без необходимости перемещать класс за пределы блока. не знаю, вроде:

.grandparent {
  .parent {
    /.child {   // Ordered logically, but outputs cleaner CSS
      background: white;
    }
  }
  background: blue;
}

или, заимствуя из верхнего примера:

.grandparent {
  .parent {
    &{0}.child {   // inherit NONE of the parents
      background: white;
    }
  }
  background: blue;
}

Оба выводят:

.grandparent {
  background: blue;
}
.child {
  background: white;
}

Мысли?

Все 118 Комментарий

Пример использования:

.main-content {
    .button {
        .button-icon {
            background-image: @button-icon;
            (.button):hover { background-image: @button-icon-hover; }
            (.button).focus { background-image: @button-icon-focus; }
            .ie8 (.main-content) { background-image: @button-icon-ie8; }
        }
    }
}

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

В LESS есть множество решений для этого. Вы можете назначать переменные и использовать их как часть цепочек селекторов (я думаю, это новое в 1.3.1). & на самом деле не является родительским селектором в смысле этого термина в CSS4. Он буквально просто добавляет унаследованные селекторы туда, где вы их размещаете.

Обычно я заканчиваю тем, что пишу эти блоки кода следующим образом:

.main-content {
    .ie8 & { background-image: @button-icon-ie8; }
    .button {
        &:hover { background-image: @button-icon-hover; }
        &.focus { background-image: @button-icon-focus; }
        .button-icon {
            background-image: @button-icon;
        }
    }
}

Я делаю то же самое — дублирую свои вложенные блоки с переопределениями. В реальном сценарии это приводит к неуправляемому количеству дублирования.
К вашему сведению, в вашем примере background-image необходимо применить к .button-icon , поэтому у вас будет больше дублирования.

Можете ли вы объяснить «назначить переменные и использовать их как часть цепочки селекторов»?

Я, вероятно, ошибаюсь в этой цитате, поэтому, вероятно, не стоит пытаться ее объяснить. То есть лично я не пробовал.

Итак, похоже, что вы хотите изменить селектор в унаследованной цепочке. Как это будет работать в данном случае?

.button {
.main-content {
    .button {
        .main-content {
            .button-icon {
                background-image: @button-icon;
                (.button):hover { background-image: @button-icon-hover; }
                (.button).focus { background-image: @button-icon-focus; }
                .ie8 (.main-content) { background-image: @button-icon-ie8; }
            }
        }
    }
}
}

Это запутанный CSS, но вполне корректный CSS.

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

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

Единственная проблема — мешает ли это каким-либо существующим правилам селектора CSS? Глядя на анализатор less, я вижу, что элемент селектора может соответствовать /\([^()@]\)/ , что означает, что он уже анализируется правильно. Я не знаю, допустимы ли эти скобки.

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

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

Принимая во внимание, что & уже достаточно мощный, и мы вводим :extend() в 1.4.0, мне кажется, что единственное, чего не хватает, — это возможность вызвать миксин, который добавляет селекторы к вашему цепочка селекторов, то, если мы решим добавить эту функциональность, она должна быть максимально простой. Чем больше мы добавим селекторов, тем сложнее будет научиться и понять.

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

Я согласен. Это чрезмерное усложнение является результатом очень сложной структуры МЕНЬШЕ, и, вероятно, лучше было бы потратить время на упрощение кода МЕНЬШЕ, а не на внедрение очень сложного синтаксиса.

Я собираюсь снова открыть это. Мы видели вариации этой идеи (например, #1154), и я чувствую, что есть возможность решения.

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

Кроме того, бывают случаи, когда люди хотят унаследовать НЕКОТОРЫЕ части стека, но не все.

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

.main-content {
    .button {
        .button-icon {
            background-image: @button-icon;
            &{2}:hover { background-image: @button-icon-hover; }
            &{2}.focus { background-image: @button-icon-focus; }
            .ie8 &{3} { background-image: @button-icon-ie8; }  // In this case, &{3} is the same as & because it goes to top
        }
    }
}

По сути, шагните «вверх» по дереву наследования до уровня, который мы хотим наследовать/добавить к текущим селекторам.

Или что-то вроде «нарушения» наследования и начала заново без необходимости перемещать класс за пределы блока. не знаю, вроде:

.grandparent {
  .parent {
    /.child {   // Ordered logically, but outputs cleaner CSS
      background: white;
    }
  }
  background: blue;
}

или, заимствуя из верхнего примера:

.grandparent {
  .parent {
    &{0}.child {   // inherit NONE of the parents
      background: white;
    }
  }
  background: blue;
}

Оба выводят:

.grandparent {
  background: blue;
}
.child {
  background: white;
}

Мысли?

Мне это нравится. Я предпочитаю мое предложение &1 или @Soviut &(1) . Я думаю, что, вероятно, это мой нынешний победитель.

Одна мысль. Решение Мэтьюса не позволяет вам иметь миксин (с неизвестным наследованием) и просто работать с вашими текущими селекторами (как в # 1158). Слишком сложно иметь &(2..n) .var &(1) ? или вы можете сделать & .var &(1) и первыми & будут все селекторы, которые еще не выбраны. в качестве альтернативы, следует ли по умолчанию помещать части селектора, которые вы не используете в начале, если вы не используете \ ?

Один вопрос: почему &(1) , а не &{1} ? Последний похож на синтаксис встроенных переменных, тогда как круглые скобки напоминают математическую операцию. Или миксин, и он ни на что не похож. Это больше похоже на отсылку.

Как это сломает миксины? Не понимая этого.

в селекторе у вас есть много псевдоклассов, использующих скобки, а затем у вас есть подстановка переменных, которая заимствует свой синтаксис из более подробного ~"@{var}", поэтому для меня обычные скобки работают лучше (особенно если мы должны разрешить &(2..n) ).. но, сказав, что у меня нет сильного предпочтения между ( и { .. Меня больше интересует вышеизложенное .. как перейти на 1 уровень наследования по сравнению с выход из текущего селектора.

Я удивлен, что никто не упомянул, как нацеливаться на конкретных (непосредственных) родителей, когда присутствует более одного. Вот некоторые CSS, к которым я хотел бы прийти:

/* regular css */
.foo, .bar {
    margin: 0 auto;
    line-height: 1.2;
}
.bar {
    line-height: 2;  /* override */
}

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

/* LESS css */
.foo, .bar {
    margin: 0 auto;
    line-height: 1.2;

    &(2) {
        line-height: 2;
    }
}

Затем к предкам можно было получить доступ с помощью дополнительных комбинаторов & (мне нравится идея «нацеливания по уровням»):

/* LESS css */
.mommy {
    .foo, .bar {
        margin: 0 auto;
        line-height: 1.2;

        &(2) {
            line-height: 2;
        }

        /* same results for &&(1) */
        &&.mommyClass {
            color: #000;
        }
    }
}

@Smolations , которые появились в другом выпуске.

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

А, я понимаю, что вы имеете в виду. Я просто не видел эту ветку проблемы, потому что ее тема не привлекла моего внимания (вы случайно не знаете, где я могу найти это обсуждение, не так ли? =] ).

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

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

здесь https://github.com/cloudhead/less.js/issues/1174

для каждой функции мы хотели бы убедиться, что она имеет реальную добавленную стоимость.. если это упрощает не рефакторинг вашего css для улучшения структуры, тогда у него нет добавленной стоимости. если это делает вас менее трудным для понимания, это нехорошо, и если это затрудняет обучение, это тоже нехорошо. Итак, я в основном поддерживаю простую функциональность в этом посте (но недостаточно, чтобы сделать ее высокоприоритетной — к сожалению, есть вещи поважнее), но я действительно опасаюсь, насколько сложной она должна стать. Если мы объединим две существующие функции, которые были запрошены, и в качестве побочного продукта позволит вам делать то, что вы хотите, не усложняя селекторы, я думаю, что это лучше, если ваши варианты использования не являются достаточно общими, чтобы добавить специальные функции. потому что у них так много добавленной стоимости.

давайте посмотрим, сможем ли мы переписать ваш последний пример...

.mommy {
   .foo, .bar {
       margin: 0 auto;
       line-height: 1.2;
   }
   .bar {
       line-height: 2;
   }
   .mommyClass {
       color: #000;
   }
}

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

.mommy {
   .foo {
       margin: 0 auto;
       line-height: 1.2;
   }
   .bar:extend(.mommy .foo) {
       line-height: 2;
   }
   .mommyClass {
       color: #000;
   }
}

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

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

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

Для «экранирования» я думал о >| или что-то в этом роде.. но да, если нам действительно нужны определенные родительские селекторы &(0) для экранирования, а остальные для таргетинга на определенный уровень вложенности, похоже, делают некоторые смысл.

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

Мы представляем & в SassScript как список разделенных запятыми значений. Затем все манипуляции с селекторами можно выполнять в «пользовательском пространстве», просто манипулируя селекторами с помощью функций Sass.

Например:

.foo, .bar > a { first: nth(&, 1); second-combinator: nth(nth(&,2),2) }

будет генерировать:

.foo, .bar > a { first: ".foo"; second-combinator: ">"}

У нас будет эта функция в Sass 3.3. Я подозреваю, что мы также добавим несколько стандартных функций управления селекторами, а затем подождем, чтобы увидеть, что разработает сообщество, прежде чем стандартизировать что-либо еще.

@chriseppstein , хорошо, мне очень нравится гибкость этого подхода. Спасибо

@jonschlinkert :) & — это функция, которую Less перенял из Sass; Я думаю, что сообществу разработчиков будет лучше, если они оба продолжат работать одинаково.

@chriseppstein Это довольно круто, мне нравится, как & действует как переменная, с которой вы можете выполнять функции. Делает эту концепцию намного проще для понимания и чтения.

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

<strong i="7">@a</strong>:~".c";
@{a}.b {
   & + & {
      .d(nth(&, 1));
   } 
}

возьмем приведенный выше пример.. Мы делаем это

  1. позвони .d
  2. оценить @{a}.b
  3. потренироваться & + &

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

Этапы 1 и 2 выполняются на одном этапе, а этапы 3 — на другом.

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

Я думаю, чтобы реализовать это, вам нужно иметь представление о том, находится ли набор правил в состоянии смешивания или нет, и в момент, когда он выходит из этого состояния (или в начале оценки, если он никогда не смешивался), мы работаем селекторы. Я думаю, это сработает. Тогда мы могли бы получить пути во время оценки.

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

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

Мне придется подумать об этом.

Как это будет взаимодействовать с функцией «возврат миксинов» https://github.com/cloudhead/less.js/issues/73 ?

Что будет результатом этой операции:

.some-class {
  #unlock-this {
    .mixin() {
      first: nth(&, 1); 
    }
  }

  .foo, .bar > a { 
    #unlock-this();
    .mixin();
  }
}

Это может быть либо это:

.some-class .foo,
.some-class .bar > a {
  first: #unlock-this;
}

или это:

.some-class .foo,
.some-class .bar > a {
  first: .some-class .foo;
}

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

Похоже, здесь есть что-то мощное для ссылки на унаследованный селектор. Интересный.

Мне все еще нравится идея простого escape-символа, чтобы просто отключить наследование блоков без лишней шумихи. CSS Crush использует знак вставки ^ . Кажется простым. Как насчет этого?

.this {
  .is {
    .deeply {
      .nested {
        ^.related-but-simpler-output {
          property: awesome;
        }
      }
    }
  }
}

// Outputs

.related-but-simpler-output {
  property: awesome;
}

Материал nth() тоже классный (для «выбора» унаследованного селектора), который, я не думаю, будет противоречить поддержке этого.

+1 за способ ссылки/нацеливания на конкретный родительский селектор с использованием некоторого синтаксиса dict, например &2 или &{2} или &^^ или даже &~2 ( эти последние два предложения вдохновлены git).

+1 за способ отключить наследование блоков (как было предложено чуть выше @matthewdl). Этот запрос является мечтой, так как он позволяет сократить вывод, в то же время используя блоки с областью действия (и переменные) во время предварительной обработки.

Я считаю, что эти две функции (селектор целевого родителя и наследование escape-блока) будут очень полезны для тех, кто пытается писать CSS, следуя методологии БЭМ .

Мы представляем & в SassScript как список разделенных запятыми значений.

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

Это просто, но без разделения пространства.

.one {
  &.two {       & inherited value is == ".one"  
    &.three {   & inherited value is == ".one.two".
       &1:hover { }  // Outputs .one.two.three:hover { } &1 always == & 
       &2:active { }  // Outputs .one.two:active { }
    }
  }
}

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

.parent1, .parent2 > .immediate-child {
  &.child1, .child2 {
    .box, .getting-complicated {
      // &2 is easy to understand here if it refers to "&.child1, .child2", but...
     nth(nth(nth(&,4),1),2) { } // or whatever it would be to breakdown lists of lists of lists
    }
  }
}

Я понимаю, что это мощно. Но действительно ли это проще? Или нужен?

nth(nth(nth(&,4),1),2) { } // или что бы это ни было, чтобы разбивать списки списков списков

Лол, я понимаю вашу точку зрения, но не могли бы мы показать примеры кода, чтобы показать то же самое практически со всеми функциями Less.js? Слишком большая абстракция является помехой независимо от того, о какой функции вы говорите. Точнее, кто на самом деле стал бы это делать?

Я понимаю, что это мощно. Но действительно ли это проще? Или нужен?

Восприятие - это реальность ;-) Однако верное замечание. было бы хорошо услышать больше разработчиков, таких как @maniqui

Почему это должны быть списки списков списков? & представляет текущий контекст. Так что самое большее это список списков. Первый список представляет собой селекторы, разделенные запятыми, второй список представляет собой просто последовательность простых селекторов и комбинаторов. (по крайней мере, так это будет работать в Sass).

@chriseppstein Признаться , я не совсем понимаю, как вы используете & с nth().

Как бы вы реорганизовали это:

.one {
  &.two, &.four {      
    &.three {  
       &1:hover { }  
       &2:active { }  // I want to return .one.two:active, .one.four:active { }
    }
  }
}

Моя главная мысль заключается в том, что, хотя nth() может быть отличной функцией, и я понимаю, почему она есть в SASS, я не уверен, что она напрямую решает проблему, поднятую в этой теме, а именно ссылку на конкретный узел цепочки наследования. Вместо этого это звучит так, как будто вы можете выбрать часть унаследованного значения. ... Что МОЖЕТ решить проблему, и я могу просто не понять простого использования nth().

Это похоже на какой-то хрупкий код, который вы там делаете.

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

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

.one {
  .two, .four {      
    ^.three { }  // just output .three { }
  }
}

&1, &2 все еще кажется довольно простым для осмысления.

Хорошо, вот что я хотел сделать с & :

  • & ведет себя как сейчас
  • &^1 просто перемещается на один уровень.
  • Если у вас есть списки селекторов, может быть, ссылку отдельно? Типа &^1[2] или типа того.

Ну вот так

.class {
   .child1, .child2 {
      .grandparent & { }
      .after-parent-insert &^1 { }
      .child-modifier&^1 { }
      .special-child-modifier&^1[2] { }
   }
}

Что выведет это (если бы на каждом уровне было что-то)

.class { }

.class .child1,
.class .child2 { }

.grandparent .class .child1,
.grandparent .class .child2 { }

.class .after-parent-insert .child1,
.class .after-parent-insert .child2 { }

.class .child-modifier.child1,
.class .child-modifier.child2 { }

.class .special-child-modifier.child2 { }

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

Что касается побега, мне нравится простота ^ , если это действительно кажется важным, хотя я на самом деле не чувствую, что это необходимо. Я пишу меньше, чтобы показать мне отношения. Вложение, а затем побег от чего-то, похоже, сломает это для меня. Если мне нужна переменная в нескольких областях, я думаю, что просто оберну все в & { } и объявлю там переменные.

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

&^-1

Кроме того, как насчет пограничного случая, когда вы хотите использовать & в качестве префикса? Должен ли синтаксис быть следующим?

.grandparent {
    .parent {
        .child {
            & &^1 {        // <-- trying to refer to .parent
               color: blue;
            }
        }
    }
}

В этой ситуации, с чего начинается индекс? Первоначально у меня было искушение написать &^2 , но технически первый & указывает, что я уже имею дело с элементом .child , поэтому мне нужно только подняться на 1.

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

Если я вас правильно понял, я определенно согласен с тем, что вложение помогает отображать отношения, в большинстве случаев помогая сделать код коротким и лаконичным, но, надеюсь, все еще читабельным [1]. С другой стороны, «плоские лучше, чем вложенные» [2].

Хотя люди не являются компиляторами, в контексте компиляции CSS легко увидеть, что при слишком глубоком вложении (более 2 уровней) (ab) использование & компилирует более длинные селекторы, таким образом, генерируя более длинные выходные данные. .
Более длинные селекторы обычно означают более высокую (ненужную_ более высокую) специфичность, что в большинстве случаев нежелательно. Ненужная высокая специфичность может легко привести к обратному эффекту.
Более длинный вывод означает, конечно, большие файлы. Опять же, мы, люди, не компиляторы, но мы знаем свое мастерство и знаем преимущества наличия кода, который компилируется в более короткие файлы.

Мы пишем наш CSS в LESS, чтобы писать _less_ и, возможно, компилировать в _less_ количество кода.
Иногда я виноват в том, что пытаюсь быть слишком умным при написании своего LESS-кода. Моя будущая я обычно ненавидит меня, так как я обычно заканчиваю тем, что стреляю себе в ногу из будущего.

Итог: я сталкивался с ситуациями (в частности, при написании CSS по методологиям BEM/SUIT), когда & вообще не помогал, а наличие «немедленного родительского селектора» (что-то вроде предложенного ^ ) было бы действительно полезно. Конечно, я не задокументировал эти ситуации, и теперь я не могу привести реальный пример.

[1] Должен ли код быть коротким/кратким?: http://stackoverflow.com/questions/952194/should-code-be-short-concise
[2] Дзен Python: http://www.python.org/dev/peps/pep-0020/

(Честно говоря, все это выглядит как своего рода чрезмерная инженерия... Или, может быть, я просто не совсем понимаю возможные варианты использования).
В любом случае, не является ли «численный родительский таргетинг» немного хрупким? Видите ли, вы делаете некоторые изменения во внешних селекторах (например, вставляете или удаляете селектор) и... бум! вы должны исправить (или, по крайней мере, проверить, нужно ли вам исправлять) все эти индексы во вложенных блоках. Просто мысль...

+1 за эту проблему.

1575 - это дубликат, который я создал, потому что github не позволяет вам искать буквальные & , и в то время я не знал о терминологии «родительский селектор» и «добавочный». На самом деле, я собираюсь добавить сюда термин «амперсанд» на тот случай, если кто-то еще начнет его искать.

Там есть довольно дистиллированный вариант использования / объяснение ожиданий, если вы хотите его прочитать.

У меня нет твердого мнения о синтаксисе этой функции. Я ожидаю, что текущая объемлющая область является той, на которую чаще всего будут ссылаться, поэтому синтаксис для этого должен быть кратким. Такие варианты, как &^ и &_n_ , кажутся мне отличными.

Просто хочу добавить, что мы не хотим менять поведение по умолчанию.. и было изобретено
в первую очередь для добавления :hover и т. д. Без пробела.

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

Меня интересуют варианты использования, которые не просто... Arggg, я не хочу
рефакторинг этого блока селектора..

Я не против этой функции в принципе, но она рискует добавить
особенность, которая делает людей менее трудными для отслеживания и поддержки.

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

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

/* a block (.block) */
.myblock {
  prop: value;
}

/* an element (.block__element) */
.myblock__date {
  prop: value;
}

/* an element (.block__elementB) nested inside an element (.block__elementA)
.myblock__date .myblock__year {
  prop: value;
}

/* an element (.block__elementC) nested inside an element (.block__elementB) nested inside an element (.block__elementA) 
.myblock__date .myblock__year .myblock__digit {
  prop: value;
}

/* an element (.block__elementB) present in a particular modified context (.block__elementA--modified) */
.myblock__date--end .myblock__year {
  prop: value;
}

/* idem */
.myblock__date--end .myblock__digit {
  prop: value;
}

/* an element modified (.block__elementA--modifier) present in a particular context (.block__elementD) */
.myblock__header .myblock__date--end {
  prop: value;
}

/* an element (.block__elementC) nested in a particular modified context (.block__elementA--modifier) nested in a particular context (.block__elementD)  */
.myblock__header .myblock__date--end .myblock__year {
  prop: value;
}

Я буду экспериментировать. Может быть, кто-то еще хотел бы поделиться, как бы они решили это?

@маникви

Есть ли какая-то особая причина, по которой вы хотите добавить к каждому классу префикс «.myblock__»? Если эти элементы являются потомками корневого элемента .myblock, то не будет ли более последовательным что-то вроде .myblock .date .year .digit ? А если они не потомки, то действительно не совсем просто понять, какое отношение они вообще имеют к классу ".myblock" (и почему они так называются)...
Что ж, если вам действительно нужно префикс всего с одним и тем же префиксом, тогда:

.my-elements(~'.myblock__');

.my-elements(@-) {

    @{-}date {
        prop: value;

        @{-}year {
            prop: value;
            @{-}digit {
                prop: value;
            }
        }

        &--end { 
            @{-}year {
                prop: value;
            }

            @{-}digit {
                prop: value;
            }

            @{-}header & {
                prop: value;

                @{-}year {
                    prop: value;
                }
            }
        }
    }
}

Да, этот код выглядит как минимум странно, но это только потому, что желаемый CSS сам по себе странный (поэтому мне собственно интересно, каким будет соответствующий HTML).
Но главная проблема заключается в том, что этот пример больше касается «обработки строк», а не слишком много о «нацеливании на родительский объект»… И если речь идет о «нацеливании на родительский элемент», то… ммм… конечно, если все эти классы элементов вложенные в HTML в почти случайном порядке, вам нужна специальная механика (например, «родительский таргетинг»), чтобы преобразовать эту «случайную» структуру в «не такой уж случайный» МЕНЬШИЙ код... но для этого ли предназначен МЕНЬШЕ?


Обновление: сделал небольшие изменения в коде (свернул --end ). теперь это еще более странно, дох!

@семь фаз-макс

Этот способ написания CSS основан на соглашениях об именах таких методологий, как BEM и SUIT .

Что касается того, как вы это написали, я использую аналогичный подход.

& { // This creates a scope for variables.
  <strong i="10">@block</strong>: myblock;

  .@{block} {
   prop: value;
  }

  .@{block}__date {
    prop: value;    
  }

  .@{block}__date .@{block}__year  {
    prop: value;
  }

  .@{block}__date .@{block}__year .@{block}__digit  {
    prop: value;
  }

  .@{block}__header .@{block}__date {
    prop: value;
  }

  .@{block}__header .@{block}__date .@{block}__year {
    prop: value;
  }  
}

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

А, теперь понятно... Так разве все эти БЭМ-вещи не предназначены для автоматической генерации CSS из некоторых шаблонов (используя специальные инструменты и скрипты)? Ну, неважно, вашего примера достаточно, чтобы я никогда даже не думал писать CSS (с МЕНЬШЕ или без) вручную, используя эти соглашения БЭМ :)

@maniqui Продолжаю играть с вашим примером ... Я думаю, что это все еще интересное упражнение (с удаленным префиксом раздувания). В контексте возможных улучшений читабельности я подозреваю, что ключ будет просто пытаться собрать свойства похожих элементов вместе. Например, если элементы .year, .digit и .date имеют схожие свойства, я бы закончил примерно так:

.date {
            &             {prop: value}
    .header &--end        {prop: value}

                   .year  {prop: value}
            &--end .year  {prop: value}
    .header &--end .year  {prop: value}

             .year .digit {prop: value}
            &--end .digit {prop: value}
}

(Использование «компактной» формы только для экономии времени на форматирование, конечно, это не будет так «чисто» с несколькими свойствами для каждого элемента). И этот код кажется очень похожим на ваш последний фрагмент. Т.е. похоже, что вложенность определенно является врагом в подобных ситуациях - она ​​может сделать код более компактным и помочь удалить дубликаты, но в то же время, вероятно, убьет читабельность, если соответствующая вложенность HTML не будет очень строгой и структурированной.

Просто собираюсь бросить здесь прецедент.

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

Например, при расширении дочерний селектор должен отображаться с дополнительным содержимым и т. д.

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

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

Строка .is-expanded& вызывает селектор items.is-expanded > .item > .item-secondary , тогда как я действительно хочу .items > .item.is-expanded > .item-secondary .

.items {

  .item {

    // Margin/transition.
    & {
      transition: 100ms margin;
      .is-expanded& { .mvs; }
    }

    // Border radius.
    &:last-child { border-radius: 0 0 2px 2px; }
    &.is-expanded & { border-radius: 2px !important; }

    // Display.
    & > .item-secondary {
      display: none;
      .is-expanded& { display: block !important; }
    }

  }

}

Для меня самым простым предложением синтаксиса Less было &1 , &2 и т. д., где 1 был первым родительским селектором. Очень натуральный, легко грок.

Так что в этом случае я бы просто использовал .is-expanded&2 .

Когда вы хотите что-то вроде .grandparent.black .parent .child
Я думал о чем-то подобном, но мне нравится число вроде &(3)
но тогда это становится запутанным, потому что он затем добавляет остальную часть текущего селектора к этому селектору? или это должно быть похоже на &(3).black & , который затем применит текущий селектор, в котором мы находимся? или он будет автоматически наследоваться? Был бы случай, когда вы не хотели бы, чтобы он автоматически наследовал? Если бы мы не хотели, чтобы он наследовал, то он не был бы записан в селекторе .parent .child, поэтому он должен наследоваться.

.grandparent {
  .parent {
    .child {
      background: white;

      &&&.black {
        background: black;
      }
    }
  }
}

&:1 — мой любимый ( :1 здесь ведет себя как псевдоселектор). Синтаксис :extend() уже соответствует стандартному синтаксису псевдоселектора, определенному в CSS, поэтому я чувствую, что псевдоподобный синтаксис подойдет очень хорошо. & — это вещь, &:1 — это подмножество этой вещи, точно так же, как a и a:hover . Зачем изобретать велосипед, понимаешь?

&(1) делает & похожей на функцию, а не на строку селектора, и я бы не хотел просто &1 , потому что если у меня есть, например, стили столбцов, которые я выбираю для определить, как показано ниже, они должны быть в значительной степени переписаны (возможно, также потребуются изменения в моей разметке).

.col {
  &1 { /* stuff */ } // .col1
  &2 { /* stuff */ } // .col2
  &3 { /* stuff */ } // .col3
  ...
}

&:1 представляет гораздо меньшую угрозу для текущих таблиц стилей (я не могу придумать, по какой причине :1 может быть в таблице стилей, так как это недействительный CSS и его нельзя использовать как хук JS или что-то еще) и, вероятно, никогда не будет мешать каким-либо псевдоселекторам или элементам CSS, текущим или будущим. И, как я упоминал ранее, это концептуально согласуется с другими функциями Less.


Кстати, &[1] (синтаксис селектора атрибутов) тоже имело бы смысл. И это похоже на синтаксис массива JS, который классный и довольно хорошо соответствует идее, я думаю. Числовые атрибуты на самом деле не работают в HTML , поэтому все преимущества &:1 применимы и к &[1] .

ОБНОВЛЕНИЕ: как упоминал @SomMeri , ^ и ^^ конфликтуют с теневыми селекторами DOM.

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


Я думаю, что многие отзывы о хрупкости и чрезмерной сложности числового таргетинга имеют большое значение. Нам может понадобиться самое большее два «модификатора» для унаследованных селекторов без нумерации шагов в дереве. Может быть, следующее более интуитивно понятно?

  • < — расширение концепции дочернего CSS-модификатора, родительского модификатора. При использовании с & опускает непосредственный родитель
  • ^ - "ускользает" от текущего контекста. При использовании с & наследует только непосредственного родителя

Каждый модификатор изменяет следующий & и только следующий. Лучше всего показать на примере.

Пример 1 — пример @vjpr

.items {

  .item {

    & > .item-secondary {
      display: none;
      < &.is-expanded ^ & { display: block !important; } 
    }

  }

}

// results in

.items .item > .item-secondary {
  display: none;
}
.items .item.is-expanded > .item-secondary {
  display: block !important;
}

_Примечание: в приведенном выше примере < &.is-expanded можно записать как <.is-expanded ._

Пример 2 - побег от дерева

Часто люди хотят «структурировать» классы Less, чтобы они соответствовали разметке (чтобы сделать их стили самодокументируемыми), но не хотят выводить больше вложенных CSS.

.books {
  float: left;
  ^ .book {
    display: inline-block;
  }
}
// results in
.books {
  float: left;
}
.book {
  display: inline-block;
}

Пример 3 — Расширенное использование

.grandparent {
  .parent {
    .child {
      background: blue;
      < < &:hover < ^ & {  
        background: red;
      }
    }
  }
}

// results in
.grandparent .parent .child {
  background: blue;
}
.grandparent:hover .parent .child {

}

В предыдущем примере < < выбирает .grandparent { } , а < выбирает .parent { } , а ^ экранирует его из .grandparent { }. Хотя это более сложный пример и, возможно, на первый взгляд странный синтаксис, я чувствую, что сам вариант использования очень «реальный мир». Когда я пишу стили, я описываю представление .child . Основываясь на состоянии наведения контейнера дедушки и бабушки, я хочу изменить текущий класс .child . Его можно преобразовать в следующую альтернативу, но на самом деле его сложнее поддерживать, потому что теперь мы описываем .child в двух разных местах и ​​дублируем классы:

.grandparent {
  .parent {
    .child {
      background: blue;
    }
  }
  &:hover {
    .parent {
      .child {
        background: red;
      }
    }
  }
}

Таким образом, хотя рефакторинг _возможен_, использование таргетинга на самом деле является лучшим СУХИМ подходом. ( @lukeapage - это может быть тот пример, который вы ищете, где таргетинг минимизирует код больше, чем может сделать рефакторинг.)

Конечно, если пользователь хочет указать, для какого именно элемента мы отслеживаем состояние наведения, он может свести к минимуму хрупкость с помощью escape и точно описать его для того же вывода:

.grandparent {
  .parent {
    .child {
      background: blue;
      ^ .grandparent:hover .parent .child {  // or you could write it ^ .grandparent:hover .parent ^ & if you wanted
        background: red;
      }
    }
  }
}

Таким образом, с двумя модификаторами мы могли бы охватить, я думаю, большинство, если не все перестановки вариантов использования без необходимости точного числового таргетинга. Мысли?


_EDIT: я нашел то, что считаю лучшим решением.

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

.grandparent {
  .parent {
    .child {
      background: blue;
      << &:hover ^^ & {  
        background: red;
      }
    }
  }
}

По сути, учитывая цепочку конкатенации (&) [.grandfather][.parent][.child] и используемую с & , < удаляет последнюю в цепочке, а ^ «включает» элементы в цепочке, начиная с конца.

Так:
<< & = [.grandfather] [.parent][.child]
^^ & = [.grandfather] [.parent][.child]

^ сам по себе удалит все: [.grandfather][.parent][.child]

Конечно, мне пришло в голову, что ^ используется как «начинается с» в качестве селектора атрибутов. Так что может иметь смысл зарезервировать это для потребления цепи спереди. Так как ^ является корнем текущего дерева, а ^^ может быть первым элементом дерева.

Что интуитивно понятно другим людям?


_EDIT: я нашел то, что считаю лучшим решением.

@matthew-dean Селекторы ^ и ^^ будут конфликтовать с селекторами ShadowDOM cat ( ^^ ) и hat ( ^ ), которые уже поддерживаются less. js # 1801 .

@SomMeri Точно , дерьмо, забыл об этом. Что вы думаете о том, что < & относится к «родительскому контексту для &»?


_EDIT: Вам не нужно отвечать на это.

Я больше игрался с синтаксисом, селекторами и различными примерами, и я вернулся к синтаксису, который был близок к тому, с чего @scottrippey пришлось начинать. Я начал писать разные примеры с $ (атрибут CSS «заканчивается» селектором) вместо ^ , но это просто начало читаться как уродливое регулярное выражение.

В конце концов, со всеми различными селекторами, я обнаружил, что, вероятно, проще всего было бы не пытаться «перемещаться» вверх по дереву и выбирать его по номеру (что неясно) или по символу (который все еще может быть трудно определить, какой именно). parent, о котором вы говорите), но на самом деле указать, какой селектор в цепочке селекторов & вы действительно имеете в виду.

.grandparent {
  .parent {
    .child {
      background: blue;
      &(.grandparent):hover {  
        background: red;
      }
    }
  }
}

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

Итак, вернемся к примеру @vjpr :

.items {
  .item {
    & > .item-secondary {
      display: none;
      &(.item).is-expanded { display: block !important; } 
    }
  }
}

Преимущество такого подхода в том, что он читается очень чисто, определенно читается чище, чем мои предыдущие примеры с << и ^^ . Я включаю весь контекст & , но изменяю один из селекторов в моей цепочке селекторов. Совершенно не двусмысленно, какой родительский элемент я имею в виду или какой класс я хочу к нему присоединить. Там же написано ясно.

Чем больше я смотрю на это, тем больше я понимаю, что это наиболее читаемое, наименее двусмысленное и наименее хрупкое решение для различных токенов и числовых ссылок. Он больше похож на :extend, но вместо &.

Я думаю, что @scottrippey был прав с самого начала, хотя я предпочитаю &(.selector) просто (.selector) , чтобы указать особый случай & , а не что-то похожее на анонимную функцию.

Мне это нравится. Имеет интуитивное ощущение этого.

отправлено из моего Айфона

15 июля 2014 г., в 17:14, Мэтью Дин уведомления[email protected] написал:

Я больше игрался с синтаксисом, селекторами и различными примерами, и я вернулся к синтаксису, который был близок к тому, с чего @scottrippey пришлось начинать. Я начал писать разные примеры с $ (атрибут CSS «заканчивается» селектором) вместо ^, но это просто начало читаться как уродливое регулярное выражение.

В конце концов, со всеми различными селекторами, я обнаружил, что, вероятно, проще всего было бы не пытаться «перемещаться» вверх по дереву и выбирать его по номеру (что неясно) или по символу (который все еще может быть трудно определить, какой именно). parent, о котором вы говорите), но на самом деле указать, какой селектор в цепочке селекторов & вы действительно имеете в виду.

.дедушка {
.родитель {
.ребенок {
фон: синий;
&(.прародитель):наведите {
фон: красный;
}
}
}
}
Итак, как было предложено, & становится похожей на функцию, которая может содержать нулевые аргументы для объединения всего списка или может принимать аргументы для изменения вывода списка.

Итак, вернемся к примеру @vjpr :

.Предметы {
.пункт {
& > .item-вторичный {
дисплей: нет;
&(.item).is-expanded { display: block !important; }
}
}
}
Преимущество такого подхода в том, что он читается очень чисто, определенно читается чище, чем мои предыдущие примеры с << и ^^. Я включаю весь контекст, но изменяю один из селекторов в моей цепочке селекторов. Совершенно не двусмысленно, какой родительский элемент я имею в виду или какой класс я хочу к нему присоединить. Там же написано ясно.

Чем больше я смотрю на это, тем больше я понимаю, что это наиболее читаемое, наименее двусмысленное и наименее хрупкое решение для различных токенов и числовых ссылок. Он больше похож на :extend, но вместо &.

Я думаю, что @scottrippey был прав с самого начала, хотя я предпочитаю &(.selector) просто (.selector), чтобы указать особый случай &, а не что-то похожее на анонимную функцию.


Ответьте на это письмо напрямую или просмотрите его на GitHub.

Да, и извинения перед @scottrippey за то, что он отклонился от своего синтаксиса. Я даже не понял, что он имел в виду по поводу ненужного количества дублирования, пока не просмотрел несколько других примеров, а позже не имел собственного опыта, пытаясь решить ту же проблему. Это действительно кажется наименее проблематичным способом настроить родителя для дочернего стиля СУХИМ способом.

На самом деле нет ничего плохого в использовании ^ и ^^ , поскольку они больше не используются для селекторов ShadowDOM (заменены на /deep/ и т. д., см. #2023 — так что нам придется удалить материал #1801). Всегда есть опасения по поводу использования любого универсального символа в определении селектора (и даже & не является исключением :), так как они _могут_ выбрать любые символы, которые захотят для CSS (хотя где-то в списках рассылки ходили слухи, что обещаю никогда больше так не делать).

Я имею в виду, что мы все еще можем помнить о синтаксисе ^ и ^^ (если только кто-то не собирается реализовывать эту функцию прямо завтра).


Мне тоже нравится идея &(selector) . Единственная проблема, которую я вижу, это (ну, довольно искусственный пример):

ul {
    li {
        ul {
            li {
                &(ul):hover a {color: red} // which one?
            }
        }
    }
}

А, и у нас уже был такой вопрос в https://github.com/less/less.js/issues/1075#issuecomment -11350357.

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

  • &(ul) выше должен указывать на верхний уровень ul
  • и &(ul li ul) чтобы указать на вложенный ul (или использовать порядковый синтаксис CSS, т.е. любите писать беспорядочные цепочки CSS? - тоже получите свой беспорядочный Less :).

И еще одна проблема, в настоящее время следующий код действителен и компилируется, как и ожидалось:

p:nth-child {
    &(2) {
        color: potato;
    }
}

Это не сломается? (Обратите внимание, что значение в скобках также может быть @{var} , поэтому мы не можем различить два признака по простому условию число/не число).

На самом деле нет ничего плохого в использовании ^ и ^^, поскольку они больше не используются для селекторов ShadowDOM.

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

Для примера &(ul) я думаю, что это нормально, что он относится к обоим. В этот момент нам не нужно спасать разработчика от самого себя, и это делает его простым. т.е. в какой-то момент предложение рефакторинга допустимо. Это в основном поиск совпадений в списке наследования. ИЛИ мы рассматриваем его как расширение, аналогично вашему второму примеру &(ul li ul) , и вы вынуждены выписывать все предыдущие селекторы, соответствующие этому внутреннему селектору: например, &(.grandparent .parent) для ссылки на .parent { } в .grandparent { .parent { } } вместо просто &(.parent) . Это более многословно, поэтому я не уверен, что мне это нравится, но... технически это менее двусмысленно.

В примере с n-м ребёнком... это кажется довольно выдуманным? Я понимаю, что сегодня это технически возможно, но почему бы кому-то не указать, какой nth-потомок в самом селекторе? Существуют ли другие примеры со скобками, которые действительно можно было бы использовать?

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

Спасибо за отзыв.

В примере с n-м ребёнком... это кажется довольно выдуманным?

Не совсем, посмотрите этот codepen (на самом деле это упрощенная выдержка из реального проекта, который я сейчас разрабатываю). Таким образом, мы можем рассматривать этот пример как основанный на чем-то «недокументированном», конечно, но мы не можем отрицать, что это компилируемый код, и нам лучше не ломать его.
(Код в codepen немного сложнее, чем мог бы быть, и использует дополнительные грязные хаки только для того, чтобы обойти #1973).

несовпадение селектора в цепочке наследования может привести к выводу текста в том виде, в котором он написан.

Хорошее место.

Хм.... Сегодня утром я тоже подумал:

.book:not {
  &(.harry-potter) { }
}

Однако с резервным выходом это сработает. НО двусмысленность _может_ затруднить понимание кода другим сопровождающим.

Вместо этого нам может понадобиться что-то вроде [] , например:

.book {
  &.harry-potter {
    .title {
      result: awesome;
      &[.harry-potter]:hover { result: not-awesome; }
    }
  }
  &:not {
    &(.harry-potter) { foo: bar; }
  }
}

// results in

.book.harry-potter .title {
  result: awesome;
}
.book.harry-potter:hover .title {
  result: not-awesome;
}
book:not(.harry-potter) {
  foo: bar;
}

Если () потенциально конфликтует, а {} , вероятно, сбивает с толку, это следующая лучшая скобка. Конечно, ваш селектор может иметь скобки, но в этом случае я не могу придумать селектор, который будет передан в [] в CSS. Селекторы атрибутов могут ссылаться на классы, но они пропускают точку.

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

.title {
    result: awesome;
    &&(.harry-potter):hover { 
      result: not-awesome; 
    }
}

Пока && существует в коде, вероятность конфликта &&(.selector) с кодом начинает резко уменьшаться. Просто еще один вариант.

_В качестве примечания я также заметил в этом примере, что родительский таргетинг дает преимущество в порядке вывода. «Переопределение» может следовать сразу за объявлением дочернего элемента, что не всегда может быть обеспечено рефакторингом. Еще один +1 за эту функцию._

[...] можно было бы спутать с атрибутами селектора таким же образом, в настоящее время действительный код (вероятно, даже более широко используемый, чем n-th или not ):

a {
    &[title] { // is it selector attr or just custom parent tag?
        color: banana;
    }
}

@seven-phases-max Тогда предложения? () кажется правильным синтаксисом как для CSS, так и для Less для отправки селектора в функцию, так что, может быть, &&() лучше? Или & +другой символ/обертка?

Почему бы просто не рассматривать & как массив и не обращаться к нему в стиле PHP array_slice()?

&[_компенсировать_]:

  • Получает элемент по адресу _offset_.
  • То же, что &[_offset_, 1].

&[_смещение_, _длина_]:

  • Получает _length_ количество элементов, начиная с _offset_.
  • Отрицательное _offset_ переводится как "Вся длина - |_offset_|"
  • Отрицательное значение _length_ переводится как "Вся длина - |_length_| - |_offset_|" (Возможно, я что-то путаю, но вы меня поняли.)
  • Нулевое значение _offset_ означает начало массива.
  • Нулевое значение _length_ означает остаток массива.
  • Обратите внимание, что "&[_offset_]" не совпадает с "&[_offset_,]".

Или, если вы хотите использовать функции, это может стать slice(&, offset[, length]) , но это добавляет слишком много сложности IMO.

--- о ---

Возьмите это в качестве примера и отметьте положение:

#Frame {
    & .boxHolder1,
    & .boxHolder2 {
        & > div {
            & > .title > span {
                // Stuff
            }

            html.no-js & > .title > span {
                // [Position 1]
            }
        }
    }
}

Теперь для позиции 1 мы находимся в:

html.no-js #Frame .boxHolder1 > div, html.no-js #Frame .boxHolder2 > div

Что делает "&" таким массивом:

    0               1           2                               3           4               5
[   "html.no-js",   "#Frame",   [".boxHolder1", ".boxHolder2"], "> div",    "> .title",     "> span"];

Вот что мы можем сделать (почему я привожу примеры? Это просто нарезка массива!):

&[1]        =>  #Frame
&[1, 1]     =>  #Frame
&[1, 2]     =>  #Frame .boxHolder1, #Frame .boxHolder2
&[1, 3]     =>  #Frame .boxHolder1 > div, #Frame .boxHolder2 > div
&[1,]       =>  #Frame .boxHolder1 > div > .title > span, #Frame .boxHolder2 > div > .title > span
&[, 1]      =>  .html.no-js #Frame
&[-2]       =>  > .title
&[-2,]      =>  > .title > span
&[-2, 1]    =>  > .title
&[, -3]     =>  html.no-js #Frame .boxHolder1, html.no-js #Frame .boxHolder2

Кроме того, добавив специальное значение «&», мы можем получить смещение и длину предыдущего значения «&» в текущем пути:

Обратите внимание, что мы пришли к позиции 1, сделав этот выбор:

html.no-js & > .title > span

поэтому, когда мы делали этот выбор, «&» имел в виду:

#Frame .boxHolder1 > div, #Frame .boxHolder2 > div

поэтому, когда «&» используется как _offset_ или _length_, оно преобразуется в позицию этого «&» в текущем массиве путей.

// Find the value of "&" when we were selecting into Position 1
&[&, &] =>  &[1, 3] =>  #Frame .boxHolder1 > div, #Frame .boxHolder2 > div

// Find the value of "&" and what we prepended to it when we were selecting into Position 1 (This can be empty)
&[, &]  =>  &[, 4]  =>  html.no-js #Frame .boxHolder1 > div, html.no-js #Frame .boxHolder2 > div

// Find the value of "&" and what we appended to it when we were selecting into Position 1 (This can also be empty)
&[&,]   =>  &[1]    =>  #Frame .boxHolder1 > div > .title > span, #Frame .boxHolder2 > div > .title > span

Обратите внимание, как смещение и длину можно поменять местами и изменить для «&», когда оно становится отрицательным для большего количества случаев использования:

// Find what we have prepended to "&" when we were selecting into Position 1
&[, -&] =>  &[, 1]  =>  html.no-js

// Find what we have appended to "&" when we were selecting into Position 1
&[-&,]  =>  &[-2,]  =>  > .title > span // I am dying to be able to select this!

Почему я умирал, чтобы выбрать это:

#Frame {
    & .boxHolder {
        & > div {
            & + & {
                //This selects "#Frame .boxHolder > div + #Frame .boxHolder > div" which is useless.

                margin-top: 10px;
            }

            & + &[-&,] {
                //This selects "#Frame .boxHolder > div + div" which is what we want.

                margin-top: 10px;
            }
        }
    }
}

--- о ---

Примечания:

  • Использование [] может привести к путанице с селектором атрибутов. Могут ли атрибуты начинаться с «&», «-» или цифры? Насколько я знаю, они не могут, поэтому у парсера с этим проблем не будет, а вот у разработчиков могут. Использование () может быть более подходящим.
  • Некоторые люди хотели иметь способ выбрать одного члена профсоюза. Например, выбрав «h1» в этом примере:
.myBox {
    & h1,
    & h2 {
        & > span {
            /*
                To only select ".myBox h1 > span" here, you have these "tools":

                &[, &-1]    =>  .myBox
                &[-&,]      =>  > span

                So you can:
                &[, &-1] h1 &[-&,] {
                    //Selected ".myBox h1 > span"
                }

                Or just this for the sake of simplicity by sacrificing flexibility:
                &[, &-1] h1 > span {
                    //Selected ".myBox h1 > span"
                }
            */
        }
    }
}

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

.myBox {
    & h1,
    & h2 {
        //Shared properties
    }

    & h1 {
        //Properties unique to "& h1"
    }

    & h2 {
        //Properties unique to "& h2"
    }
}

--- о ---

В этом предложении сохранено положение "&", подобное переменной, и расширено таким образом, что каждый веб-разработчик должен ожидать от него поведения. Не многие языки поддерживают такое нарезку/подстроку (я думаю, Python поддерживает, а в Ruby есть что-то подобное), но весь этот синтаксис array[offset, length] будет реализован как для PHP, так и для JavaScript в более поздних версиях.

Введение этого типа доступа к массиву/нарезки может также пригодиться в других случаях:

<strong i="5">@color</strong>: rgba(12, 12, 12, 0.5);

<strong i="6">@red</strong>: red(@color);
<strong i="7">@red</strong>: @color["red"];

<strong i="8">@hue</strong>: hue(@color);
<strong i="9">@hue</strong>: @color["hue"];

<strong i="10">@color</strong>: rgba(red(@color), green(@color)*0.5, blue(@color)*0.2, alpha(@color));
@color["green"] *: 0.5;
@color["blue"] *: 0.2;

Но, конечно, это обсуждение другого вопроса.

@мэттью-дин

() кажется правильным синтаксисом как для CSS, так и для Less для отправки селектора в функцию.

Да, действительно, скобки выглядят более естественными для CSS в этом контексте. Мой +1 за это.

@АликанС

Проблемы числовой индексации родительских селекторов обсуждались выше. Теоретически он мощнее, но действительно ли он полезен на практике? (Чтение и поддержка глубоко вложенных структур, где вам нужно (буквально!) подсчитывать уровни вложенности, не кажется чем-то легким).

В любом случае это не означает, что мы (в конечном счете) не можем реализовать обе модели (например, "числовую" и "по идентификатору"). В этом случае я думаю, что идея &(offset, length) хороша.


<strong i="12">@red</strong>: @color["red"];

Что ж, Less пытается сохранить синтаксис и операторы CSS, поэтому [] определенно является чужеродным оператором для операций со списком/массивом в Less. Для этой конкретной функции (то есть «общий способ получить значение цветового канала») функция вроде color-channel(<strong i="16">@var</strong>, channel-id) была бы более уважительной к традициям Less (даже если бы она была более подробной, в конце концов, я сомневаюсь, что кто-либо использует такие манипуляции с цветом _которые_ часто ).

@color["green"] *: 0.5;

Less не является императивным языком, поэтому эта функция просто невозможна в той форме «переопределения переменных» (для получения дополнительной информации см., например, ссылки, которые я собрал там ).

Индексирование массива с помощью () немного странно, но люди с некоторым опытом работы с Visual Basic согласятся, что это не НАСТОЛЬКО раздражает. Поскольку переменные начинаются с @ а функции — с . , будет меньше путаницы, чем было бы в JavaScript, если бы он использовал для индексации () .

Реализация массивов и нарезки массивов только для этого может быть излишним, но они действительно могут помочь улучшить язык другими способами. Возможность правильно подсчитывать, индексировать и нарезать аргументы функции избавит от необходимости иметь миллионы перегрузок или цветов, теней и т. д. Возможность индексации может устранить необходимость в таких функциях, как color-channel() , red() , green() и т. д.

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

Я думаю, что мы быстро уходим от темы, поэтому просто несколько кратких замечаний (и если вы хотите продолжить обсуждение, пожалуйста, создайте новую проблему / запрос функции и / или см. ссылки ниже):

Индексация массива с помощью () немного странная

Синтаксис и семантика CSS в целом _странны_ для тех, кто знаком только с C-подобными вещами (JavaScript, PHP и т. д.).

функции с .

В Less нет функций (кроме встроенных, и они не начинаются с . ).

Умение правильно считать, индексировать и нарезать аргументы функции

Вы можете подсчитывать и индексировать аргументы примесей с помощью функций списка (а для других функций, связанных с массивами, см. соответствующие потоки, например # 1857, # 2078, # 1694, # 1421 и т. д. и т. д.)

возможность индексации может устранить необходимость в таких функциях, как color-channel() , red() , green() и т. д.

Опять же, это просто вопрос «нам нужно это _так_ часто?» вопрос - работает и противоположная аргументация: "функция типа color-channel может устранить необходимость в специальном специализированном синтаксисе". ;)
Хитрость здесь в том, что встроенные функции очень легко добавить в компилятор Less, в то время как некоторые специальные операторы довольно болезненны и раздуты в реализации, поэтому разумный подход к разработке Less таков:
«если какая-то функция не является обязательной в ядре языка, лучше сделать ее встроенной или даже функцией плагина ».

Обсуждение других функций цвета см. также в #1853.

@AlicanC Я всегда говорю людям, когда говорю о Less (или отличаю его от SASS), что CSS не предполагает, что автор является программистом и знаком со структурами программирования, как и Less. Нарезка массива и ссылка на него с помощью индексации (или нумерации), возможно, более эффективны, но также, возможно, более сложны, чем ссылка с помощью селектора. И, хотя я изначально выступал за это, я думаю, как сказал @seven-phases-max, индексированные ссылки, вероятно, излишни и не нужны в большинстве случаев использования.

Тем не менее, я также согласен с тем, что мы, вероятно, могли бы поддерживать отправку функций & to list, которые мы уже поддерживаем (или что-то в этом роде), например, extract(&, 3) для более точного инструмента для тех, кто знает, как его использовать.

В большинстве случаев мы пытаемся найти самый простой метод для большинства вариантов использования, а не самый мощный метод для всех вариантов использования, включая крайние или теоретические. ИМХО, если вам нужен программный подход к стилю с синтаксисом, подобным CSS, он доступен в SASS. Если вам нужен простой подход, похожий на CSS, который «расширяет» CSS (разновидность CSS+), то это Less, но это совсем другая тема.

@семь фаз-макс
Я просто перестану отвечать на ваши комментарии о массивах, чтобы не выходить за рамки темы. Я создам отдельный вопрос (или прокомментирую связанные вопросы) о них позже.

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

Если мы решим что-то вроде &(1) чтобы получить последний дочерний элемент из селектора, разве мы не можем:

  1. Не делайте это таким образом, чтобы мы говорили: « &(n) в Less работает так же, как &[&.length-n] в JavaScript». но заставьте его работать так же, как индексирование работает в JavaScript,
  2. Просто рассмотрите & как специальную переменную, такую ​​как @currentSelector и предоставьте всю эту потрясающую индексацию всем переменным,
  3. Если считаете нужным, добавьте:

    • Нарезка в стиле Python/Ruby/PHP 6/ES 6 @var(offset[, length]) ,

    • частный случай &(&, &) ,

    • индексация именованного ключа, например @myBackground("image")

(Пожалуйста, прокомментируйте номер 3, когда я опубликую их там, где они актуальны.)

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

@мэттью-дин
Я понимаю. Если так думают руководители проектов, то пункты 2 и 3 никогда не будут реализованы. Даже номер 1 сложен, если вы так думаете. Не то чтобы я пытался бросить вызов всей философии языка. Что решено, то решено.

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

Спасибо за внимание к моим большим кускам текста :)

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

Если это полезно, вот реальный пример:

.presentation > div {
  s {
    color: black;
    .dialogue & {
      color: white;
    }
  }
}

Я ожидал, что самая внутренняя вещь расширится до .presentation > div .dialogue s ; однако он расширился до .dialogue .presentation > div s . У меня есть еще несколько таких примеров, и я думаю, что мой единственный вариант — выбросить их из установленной мною красивой иерархии вложенности (которая, как вы можете себе представить, намного больше, чем приведенный выше фрагмент), и я думаю, что это сделает файл LESS сложнее поддерживать.

Не прочитав и половины этой страницы, мне поможет только способ подняться «вверх» по иерархии. Я не уверен, есть ли альтернативный способ сделать это в LESS.

@мвичари

Ну, есть много подобных примеров выше (в общем случае, когда вы спрашиваете о «реальных» вещах, речь идет скорее о «некоторых реальных» _использованиях_, которые не могут быть достигнуты _без_ функции, а не просто некоторые фрагмент, где можно было бы ожидать/предпочтительно использовать предложенную функцию только для DRY и/или целей синтаксического сахара (не отрицая важности DRY/synsugar материала - следовательно, функция считается полезной и отмечена "средним приоритетом").

Для вашего конкретного примера слишком много методов для достижения одного и того же без # 1075, поэтому он едва добавляет что-то новое в тему (поэтому, чтобы также ответить на @ldetomi : в итоге, поскольку похоже, что теперь это имеет некоторое соглашение по синтаксису, функция просто ждет своего добровольца, чтобы реализовать ее — нет добровольца -> нет функции).

---

Что касается вашего конкретного фрагмента, то же самое слишком легко сделать с помощью миксинов (и это только один из нескольких возможных методов):

.presentation > div {
    .s(black);
    .dialogue  {.s(gray)}
    .monologue {.s(white)}

    .s(@color) {
        s {color: @color}
    }
}

Или даже так (чтобы уменьшить количество скобок):

.presentation > div {
    .-(           black);
    .-(dialogue,  white);
    .-(monologue, gray);
    .-(prologue,  red);
    .-(catalogue, blue);
    .-(ideologue, green);

    .-(@color) {s {color: @color}}
    .-(<strong i="15">@prefix</strong>, @color) {
        .@{prefix} {.-(@color)}
    }
}

.Как видите, единственная разница заключается в использовании .s или .- вместо & (и имя миксина не зависит от фактического имени элемента s ) .

@семь фаз-макс, спасибо. Тем не менее, эти примеры выглядят довольно мучительно — их сложно понять и поддерживать, особенно если учесть, что я оставил цвет и один класс только для простоты (здесь гораздо больше свойств и классов, и они не отображают 1:1).

Эти примеры выглядят довольно душераздирающими

Они? Или это только потому, что миксины не используются ;)? (Боюсь, тот же аргумент применим к .dialogue &(1) , когда кто-то видит это впервые...).

там еще много свойств и классов, и они не отображаются 1:1

В этом случае _nesting_ вообще зло, и некоторые люди (например, я) считают "плоские" селекторы более читабельными (в конце концов, вся идея помещать селектор родительского элемента в его дочерний элемент, как правило, ошибочна, у нас нет телепортации таких элементов в HTML, не так ли?), например:

.presentation > div {

    s {
        color:       black;
        font-weight: bold;
    }

    .dialogue s {
        color:      white;
        font-style: italic;
    }

    .monologue s {
        color:      gray;
        background: yellow;
    }
}

Да, там повторяется s , но читабельность того стоит ( здесь когда-то я писал бриф на это для очень похожего фрагмента).

+1 за эту функцию. Я почти начал его реализовывать, пока не нашел эту проблему. Так повезло..
Есть два момента для синтаксиса:

  1. Найдите целевой родительский селектор.
  2. Как вставить до, добавить или добавить после цели.

Мои мысли:

.table .row .cell {
    .editing &(.row) {}
    .editing &(^.row) {}
    .editing &(.row^) {}
}

соответствует:

.table .row.editing .cell {}
.table .editing .row .cell {}
.table .row .editing .cell {}

Это может быть доработано, если несколько совпадений.

@supnate Пожалуйста, посмотрите этот комментарий от @matthew-dean выше (в этом посте кратко определяется синтаксис, который выглядит как тот, который мы, наконец, более или менее согласовали как наименее проблематичный).

Мои мысли:

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

.table .row .cell {
    &(.row).editing  {} // -> .table .row.editing .cell  {}
    .editing &(.row) {} // -> .table .editing .row .cell {}
    &(.row) .editing {} // -> .table .row .editing .cell {}
}

@ Seven-Phases-Max Спасибо за ответ, извините, что не прошел предыдущее обсуждение. Однако я думаю, что разница между моей и @matthew-dean невелика. С моей стороны, важно интуитивно понимать, что имеет значение (редактирование), а затем то, где оно должно быть.

Кстати. думая о недавнем примере (подробнее о возможных деталях реализации для крайних ситуаций), вот еще одна проблема, рассмотрим следующий код:

.a .b .c .d .e {
    &(.d) .x &(.b) {}
}

Теперь вопрос: где .c и .e попадают в результирующий селектор? Честно говоря, я не могу прийти к какому-либо разумному размещению (любой результат может показаться довольно искусственным). Хотя, поскольку сам пример также является искусственным, он не выглядит реальной проблемой, поскольку мы всегда можем получить «в этом случае результат не определен/не указан» (например, «нет множественных & , относящихся к разным элементам» или что-то вроде того).

PS Ах, если подумать об этом, похоже, что это нормально, чтобы получить какой-то мусор, например:

.a .b .c .d .a .x .b .c .d .e .e {} // or
.a .a .b .c .d .x .b .c .d .e .e {}

как

.a .b .c .d .e {
    & .x & {}
}

компилируется в

.a .b .c .d .e .x .a .b .c .d .e {}

См. проблему № 2433 в связанной теме о синтаксисе «ссылки на дерево», который может применяться к локальным свойствам и свойствам родительских селекторов, и в этот момент его, возможно, стоит рассматривать как ссылку на родительские селекторы.

Пример синтаксиса:

.table .row .cell {
    ${.row}.editing  {}  // .table .row.editing .cell {}
}

Просто еще одна возможность.

Мне нравится это обсуждение!

Я пробовал это, но это не работает:

.feature {
  .feature-header:hover {
    background: red;
    @saved-context: &;
    .anotherTheme {
      .special-case-one,
      .special-case-two {
        & @{saved-context} {
          background: green;
        }
      }
    }
  }
}

/* expected output */
.feature .feature-header:hover {
  background: red;
}
.anotherTheme .special-case-one .feature .feature-header:hover,
.anotherTheme .special-case-two .feature .feature-header:hover {
  background: green;
}

/* actual output */
.feature .feature-header:hover {
  background: red;
}
.feature .feature-header:hover .anotherTheme .special-case-one &,
.feature .feature-header:hover .anotherTheme .special-case-two & {
  background: green;
}

Чтобы сделать эту работу, вам нужно будет написать:

.feature {
  .feature-header:hover {
    background: red;
    .anotherTheme .special-case-one &,
    .anotherTheme .special-case-two & {
      background: green;
    }
  }
}

Просто мои два цента.

вау вау вау такой классный так предварительная обработка

Ребята, посмотрите это обсуждение stackoverflow, чтобы узнать о некоторых других мыслях, особенно в разделе комментариев:

http://stackoverflow.com/questions/32777856/less-css-parent-selector-walking-up-only-two-three-x-steps?noredirect=1#comment53532878_32777856

В нем предполагается, что этот шаблон может быть желательным:

    // The &(1) would be all of & minus the last one.
    // The $(0, 1) would be all of & minus all of &(1)
    &(1) > .bottom > &(0, 1) {
            bottom: 0;
    }

Лично мне нравится простота предложения ctsstc :

.grandparent {
  .parent {
    .child {
      background: white;

      &&&.black {
        background: black;
      }
    }
  }
}

&&&.black

Это просто несовместимо с текущим поведением & . Кроме того, это та же «проблема ручного (пере)счета», о которой упоминалось ранее.

Я реализовал что-то подобное для SASS в inStyle , в настоящее время работая над возможными портами LESS/Stylus.

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

Синтаксис, который я выбрал, чтобы подняться вверх по иерархии вложенных селекторов: & , ^& , ^^& (...) вместо & , && , &&& . Он работает хорошо и не конфликтует ни с одним известным селектором/псевдоселектором.

Так как этот вопрос все еще открыт...

До сих пор попытка «выбрать и вставить» из родительских селекторов оказалась ужасно сложной. «Где» быстро становится двусмысленным.

Я думаю, что единственным рабочим решением, если эта функция должна была произойти, должно быть что-то похожее на «захват» и «замену», которые используются с регулярными выражениями, где вы определяете точки вставки (в этом примере помечены как ? ) которые вы используете для управления выводом позже.

.grandparent? {
  .parent? {
    .child {
      background: blue;
      &(1, :hover) {     // all selectors, but replace 1st insertion point with ":hover"
        background: red;
      }
      &(2, .active) {     // all selectors, but replace 2nd insertion point with ".active"
        background: white;
      }
    }
  }
}

в результате чего:

.grandparent .parent .child {
  background: blue;
}
.grandparent:hover .parent .child {
  background: red;
}
.grandparent .parent.active .child {
  background: white;
}

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

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

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

Что происходит с этим? Какой-либо прогресс?

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

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

@seven-phases-max К вашему сведению, я изменил stalebot, чтобы он не помечал проблему как устаревшую, если проблема каким-то образом имеет приоритет.

Я уже реализовал эту функциональность локально.

Работая с Sass с момента открытия этой проблемы, я думаю, что эту проблему можно объединить с этим предложением Less: https://github.com/less/less-meta/issues/16 .

Короче говоря, на данный момент предложение состоит в том, чтобы сделать простые селекторы (примеси) назначаемыми переменным. Мне интересно, не должно ли это стать действительным (что делает Sass):

.grandparent {
  <strong i="8">@grandparent</strong>: &;
  .parent {
    .child {
      background: blue;
      @{grandparent}:hover & //the problem here is that `&` contains .grandparent also, ideas?
        background: red;
      }
    }
  }
}

@matthew-dean Вы говорите, что это уже существует в Sass? Стилус?

Как я уже сказал, я в основном реализовал функциональность, очень похожую на ту, которую вы предлагаете, только как вызов метода:

.grandparent {
       .something {
              closest('.grandparent', { &:hover { color:red: } })

      }
}

Потратил на это больше недели. Единственная проблема сейчас заключается в том, что я предпочел бы перейти на Stylus и полностью сбросить Less, но теперь мне пришлось бы повторно реализовать эту функциональность, что доставляет хлопоты.

Если вам интересно, почему я не отправляю решение, см. здесь .

@matthew-dean Вы говорите, что это уже существует в Sass? Стилус?

Это есть в Sass. Я использовал это сегодня:

.selector {
  $sel: &;
  @at-root :global(.platform-web) {
    <strong i="7">@include</strong> responsive-margins($sel)
  }
}

<strong i="8">@mixin</strong> responsive-margin($sel: '&') {
  #{$sel} {
    margin: $gap-s auto;

    + #{$sel} {
      padding-top: $gap-m;
    }

    <strong i="9">@media</strong> (min-width: $size-phablet) {
      margin: $gap-l auto;
    }
  }
}

Мне нужно было сделать это, потому что мой миксин имел & + & , но это повторило бы мой глобальный селектор модулей CSS. Поэтому мне пришлось «сохранить» его, а затем начать с корня с глобальным классом и передать сохраненный селектор.

@matthew-dean, вы говорите, что подходите к корневому узлу (возможно, с меньшим количеством), а затем используете сохраненный селектор для ? Ваш пример неполный, так как он взят из реального источника кода. Не уверен, что он должен делать и генерировать.

В моем примере он может ориентироваться на любой селектор предков, а затем применять оттуда правило, поэтому в моем примере это

.grandparent {
       .something {
              closest('.grandparent', { &:hover { color:red: } })
      }
}

такой же как

.grandparent { &:hover { .something { color:red; } } }

@момомо

Что касается выяснения базы кода, я был бы совершенно готов рассказать вам, что я знаю/узнал о базе кода, если вы хотите взглянуть. Не стесняйтесь писать мне в личные сообщения в Твиттере, и я посмотрю, чем могу помочь - https://twitter.com/matthewdeaners

@момомо

Ваш пример не полный

Я обновил свой пример.

вопрос посчитали глупым, подвергли цензуре и закрыли

Интересный. Мне было бы любопытно, если бы кто-нибудь использовал слово «глупый». В противном случае может случиться так, что кто-то не увидит значения, и может быть трудно отстаивать свои собственные варианты использования, особенно для библиотеки общего назначения.

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

Также к этому:

Даже ребята из Sass сказали, что это невозможно.

Обратите внимание, что мой вариант использования не касается «вставки» чего-то вроде :hover в родительский (унаследованный) селектор. Таким образом, ваш вариант использования вполне мог быть невозможным в Sass, как и в Less. Итак, мой пример был только что опубликован, чтобы проиллюстрировать, что НЕКОТОРЫЕ варианты использования могут быть решены, но не решают все, включая некоторые ранее опубликованные мной.

«Таким образом, ваш вариант использования вполне мог быть невозможным в Sass, как и в Less».

Нет, это не было невозможно с точки зрения функциональности. Конечно, мне пришлось добавить метод расширения, но это было сочтено невозможным, потому что Less или Sass не могли найти, потому что они скомпилированы и не знают о своем окружении (html). Это считалось «бесполезным», никоим образом не выгодным. Ну, я думаю, ваши стандарты кодирования недостаточно хороши. Я говорил не о том, чтобы подняться по дереву dom, а о объявленном дереве css/less/sass.

На самом деле это не так сложно понять, и мой пример достаточно прост. Думаете, это сложно понять?

Мой в основном решает большинство, если не все эти проблемы.

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

Я выступал за решение for, которое позволяло вам подниматься, ориентируясь на определенный селектор, или подниматься по N родителям.

Например

closest(3, { :hover { walks up three parents } }

также работает

closest(1, { :hover { walk up one parent } } , что совпадает с &{ :hover { walk up one parent }}

closest('.someAncestorVeryHighUp', { :hover { walks up all the way up to that class } })

closest('[attribute=valueAlsoWorks]', { :hover { walks up all the way up to that attribute val match } })

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

Кроме того, вы только что повторно открыли закрытый тикет. Почему он был закрыт? Кто * * решил закрыть его? Я ненавижу Reddit, цензуру и людей, которые думают, что знают лучше или знают все ответы.

Итак, за вопрос, возникший шесть лет назад, если не больше (другие предыдущие проблемы), который был закрыт, наконец рассмотрен и решен мной без какой-либо помощи, чтобы понять этот дерьмовый код, я хочу извиниться. ( <- "Продолжайте мечтать. Это бесплатно." - spm ).

Да, звучит прямо как Трамп. Я прекрасно понимаю, но опять же, это разглагольствования.

@мэттью-дин

Говоря о вашем примере на https://github.com/less/less.js/issues/1075#issuecomment -396367364.
У нас даже есть рабочий прототип плагина для этого: https://github.com/less/less.js/issues/2619#issuecomment -115006426.
(также на https://github.com/seven-phases-max/less-plugin-reflections).
Единственная проблема заключается в том, что (даже если плагин работает так, как вы ожидаете) есть некоторые теоретические хитрости с точки зрения языка: из-за ленивой оценки значение @grandparent не должно быть "заморожено" на Строка <strong i="12">@grandparent</strong>: &; (т. е. если нет какого-то особого синтаксиса и/или какой-то конкретной функции для принудительной оценки, принцип LE предписывает, чтобы @{grandparent}:hover & расширялось до той же самой вещи &:hover & ) . Т.е. мы не можем реально сохранить это значение просто так: <strong i="17">@grandparent</strong>: &; - необходимы дополнительные исследования.

И это красивый код:

https://imgur.com/a/RWCEYtB

Весь оффтоп убран (для интересующихся перенес все обвинения со своими комментариями сюда ).

Нет, это не было невозможно с точки зрения функциональности. Конечно, мне пришлось добавить метод расширения, но это было сочтено невозможным, потому что less не мог найти, потому что он скомпилирован и не знает о своем окружении (html).

Тогда это просто кто-то совершенно неправильно понял ваш пример. Нет, ваш пример прост, и я понимаю, к чему вы стремитесь. Это запрос, аналогичный примерам «захвата» и «замены» в этой ветке, вы просто демонстрируете другой синтаксис.

Интересно, не проще ли это просто:

  1. Разрешено присваивать & переменной или в качестве параметра функции.
  2. Использование функции замены.
  3. Добавление селектора типа «в корне» ( ^ ?)

Тогда вы могли бы просто сделать:

.grandparent {
  .something {
    @grandparent-hover: replace(&, '.grandparent', '.grandparent:hover');
    ^ @{grandparent-hover} {
      color: red;
    }
  }
}

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

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

Или построить взамен? ...
🤔

.grandparent {
  .something {
    // & currently = .grandparent .something
    &:visited {
      color: yellow;
    }
    &(.grandparent; .grandparent:hover) {
      // & now = .grandparent:hover .something
      color: red;
      &:visited {
        color: blue;
      }
    }
  }
}

// output CSS
.grandparent .something:visited {
  color: yellow;
}
.grandparent:hover .something {
  color: red;
}
.grandparent:hover .something:visited {
  color: blue;
}

Spitballin '... кажется более надежным и ясным, чем ссылка на числовой индекс, которая может быть неоднозначной. Просто селекторный поиск/замена, встроенный в функцию &() .... один недостаток в том, что в будущем нам могут понадобиться другие расширения "изменения & "?

Это по-прежнему требует добавления функций:

  1. Передача селекторов в функции.
  2. & как функция

Или построить взамен? ...

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

На мой взгляд, у Sassish @at-root есть типичная проблема жестко запрограммированного бэкдора (легко взломать):

.foo {
   @at-root .bar {color: red}
}

затем в далекой галактике:

.baz {
    <strong i="14">@import</strong> "foo.less"; // oops
}

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

Этот пример выглядит немного запутанным для меня, хотя я думаю, что по сути это «захватить» и «заменить»? Я не мог сказать. Как это , но только с явными именами? Если это так, то это также разумно для меня.

На мой взгляд, у Sassish @at-root есть типичная проблема жестко запрограммированного бэкдора (легко взломать):

Я не согласен, поэтому я написал второй пример, который не требует этого. Хотя я не думаю, что это совсем лишнее. Я просто думаю, что это не должно быть встроено в потенциальное решение здесь. Я думаю, что «изменение наследования & месте», вероятно, лучше (чем что-то, использующее решение, подобное @at-root ).

Но, чтобы быть ясным, как я уже упоминал выше, захват/замена также кажется уместным.

@ Seven-Phases-Max Одна вещь, которая может помочь этой теме не крутиться вечно. Из этих решений: а) переделка на месте & , б) захват/замена, в) другое - у вас есть предпочтения? Потому что часть вращения колеса — это буквально подход, а не только синтаксис. Если бы был какой-то консенсус в отношении подхода, синтаксис мог бы в конечном итоге слиться здесь.

Что случилось с:

css  = '' +
'.body {  ' +

        '.main { ' +

            '.section {' +

                '.article {' +
                        // --- Call made here! ---

                        // Climb up to .main, and then add the selectors inside the body below
                        'closest(".main", {' +

                            '&:hover {' +
                                'background-color:red;' +   // Meaning that when you hover .main then .article will get background-color:red;
                            '}' +

                            '&.someclass {' +
                                'background-color:blue;' +   // Meaning that when .someclass is added to .main then .article will get background-color:blue;
                            '}' +

                        '})' +

                        // Do note that purpose of climbing up is to style article, nothing else.

                    '}' +

                '}' +
        '}' +
'}';

less.render( css ,function (error, output) {
        console.log('xxx');  console.log(output.css);
});

Вы можете сделать кучу других вещей два.

@момомо

Что случилось с:

Ничего особенно "неправильного" в этом нет. Фактически, Less уже некоторое время позволяет вызывать функции практически на любом узле. Таким образом, вы, вероятно, могли бы сделать это как Less @plugin . Интересно, это не лучший способ решить эту проблему.

Но что касается синтаксиса, IMO не очень подходит для языка Less, потому что в этой конструкции есть несколько странностей/выбросов, таких как заключение селекторов в кавычки и вызов функции в корне. Что вы МОЖЕТЕ сделать и определить функции для этой цели. Так что, если вы хотите решить это как плагин, вы можете сделать это сегодня, без каких-либо изменений синтаксиса Less. Он будет вызываться буквально с помощью:

<strong i="12">@plugin</strong> "closest";
.body {
  .main {
    .section {
      .article {
        // This will parse, as there's nothing invalid about this syntax
        closest(".main", {
          &:hover {
            background-color: red;
          }
          &.someclass {
            background-color: blue;
          }
        });
      }
    }
  }
}

Единственная сложная часть: любой селектор, возвращаемый closest() , все равно будет иметь все те же правила слияния. Я все еще думаю, что плагин может дать желаемое поведение.

@мэттью-дин

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

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

Пожалуйста, свяжитесь со мной по адресу ATTT momomo DOTTT com с открытым исходным кодом, и мы сможем принять его оттуда. К сожалению, я не пользуюсь твиттером.

Согласно комментарию здесь , при обсуждении того, как «использовать» захваченный селектор & , обсуждалась замена & на месте, что затем привело к этой проблеме. Поскольку это больше соответствует действительности, я подумал, что продолжу здесь то, что обсуждалось, что было похоже на то, что я упомянул на https://github.com/less/less.js/issues/1075#issuecomment -397697714.

  • &() - вернуть на место &
  • &(arg) — заменить & на arg и вернуть
  • &(arg1, arg2) — заменить arg1 в & на arg2 и вернуть как новый &

Хитрость в том, что это модификация наследования селекторов для всех последующих потомков? Или это просто модификация _для этого конкретного селектора_? Как в:

.component {
  &(.foo) .child { // selector is now .foo .child ?
    & .grandchild { // is & now .foo .child? Have we altered it permanently? I would presume yes
    }
  }
}

Кроме того, это предотвратит такие вещи, как:

.something:not {
  &(.selector) {}
}

Я не уверен, что у кого-то когда-нибудь возникнет причина написать это, но это стоит отметить.

Как насчет этого подхода:

^ - назад на один селектор
^(x) - назад x селекторы
(знак: «^» вдохновлен: http://docs.emmet.io/)

#wrapper {
  .row {

   .text-side {
      h2{
        color : #000;
        }// h2
      .text-description{
          p{
            color : #333;
            mark{
              background-color: green;
              } // mark
            } // p
        } // .text-description  
    }

    ^ .image-side {
   // avoid 1 selectors: .row
      .image-block {
        ^(2) img{
        // avoid 2 selectors: .image-block .image-side
          width: 100%;
          } // img
        } // .image-block
      } // .image-side

  }// . row
} // #wrapper

Источник: https://github.com/sass/sass/issues/2193

Была ли эта страница полезной?
0 / 5 - 0 рейтинги