深入解读 Less 特性 | Less.js 中文文档 - Bootstrap

文章推薦指數: 80 %
投票人數:10人

Less 扩充了 CSS 语言,增加了诸如变量、混合(mixin)、运算、函数等功能。

... Essentially, each scope has a "final" value, similar to properties in the ... Overview VariablesOverview VariableInterpolation VariableVariables LazyEvaluation PropertiesasVariables(NEW!) DefaultVariables ParentSelectorsMultiple& ChangingSelectorOrder CombinatorialExplosion ExtendExtendSyntax ExtendAttachedtoSelector ExtendInsideRuleset ExtendingNestedSelectors ExactMatchingwithExtend nthExpression Extend"all" SelectorInterpolationwithExtend Scoping/ExtendInside@media DuplicationDetection UseCasesforExtend MergeComma Space MixinsNotOutputtingtheMixin SelectorsinMixins Namespaces GuardedNamespaces The!importantkeyword ParametricMixins Pattern-matching UsingMixinsasFunctions RecursiveMixins MixinGuards AliasingMixins CSSGuards DetachedRulesetsScoping Property/variableaccessors @importAt-RulesFileExtensions ImportOptions reference inline less css once multiple optional @pluginAt-RulesWritingyourfirstplugin PluginScope NullFunctions TheLess.jsPluginObject Pre-LoadedPlugins Maps(NEW!)Usingvariablevariablesinlookups Overview Editthemarkdownsourcefor"overview" Anin-depthguidetofeaturesoftheLESSlanguage.SeetheOverviewforaquicksummaryofLess. Foranin-depthguidetoinstallingandsettingupaLessenvironment,aswellasdocumentationondevelopingforLess,see:UsingLess.js. Variables Editthemarkdownsourcefor"variables" Controlcommonlyusedvaluesinasinglelocation. Overview It'snotuncommontoseethesamevaluerepeateddozensifnothundredsoftimesacrossyourstylesheets: a, .link{ color:#428bca; } .widget{ color:#fff; background:#428bca; } Variablesmakeyourcodeeasiertomaintainbygivingyouawaytocontrolthosevaluesfromasinglelocation: //Variables @link-color:#428bca;//seablue @link-color-hover:darken(@link-color,10%); //Usage a, .link{ color:@link-color; } a:hover{ color:@link-color-hover; } .widget{ color:#fff; background:@link-color; } VariableInterpolation TheexamplesabovefocusedonusingvariablestocontrolvaluesinCSSrules,buttheycanalsobeusedinotherplacesaswell,suchasselectornames,propertynames,URLsand@importstatements. Selectors v1.4.0 //Variables @my-selector:banner; //Usage .@{my-selector}{ font-weight:bold; line-height:40px; margin:0auto; } Compilesto: .banner{ font-weight:bold; line-height:40px; margin:0auto; } URLs //Variables @images:"../img"; //Usage body{ color:#444; background:url("@{images}/white-sand.png"); } ImportStatements v1.4.0 Syntax:@import"@{themes}/tidal-wave.less"; Notethatbeforev2.0.0,onlyvariableswhichhavebeendeclaredintherootorcurrentscopewereconsideredandthatonlythecurrentfileandcallingfileswereconsideredwhenlookingforavariable. Example: //Variables @themes:"../../src/themes"; //Usage @import"@{themes}/tidal-wave.less"; Properties v1.6.0 @property:color; .widget{ @{property}:#0ee; background-@{property}:#999; } Compilesto: .widget{ color:#0ee; background-color:#999; } VariableVariables InLess,youcandefineavariable'snameusinganothervariable. @primary:green; @secondary:blue; .section{ @color:primary; .element{ color:@@color; } } Whichcompilesto: .section.element{ color:green; } LazyEvaluation Variablesdonothavetobedeclaredbeforebeingused. ValidLesssnippet: .lazy-eval{ width:@var; } @var:@a; @a:9%; thisisvalidLesstoo: .lazy-eval{ width:@var; @a:9%; } @var:@a; @a:100%; bothcompileinto: .lazy-eval{ width:9%; } Whendefiningavariabletwice,thelastdefinitionofthevariableisused,searchingfromthecurrentscopeupwards.Thisissimilartocssitselfwherethelastpropertyinsideadefinitionisusedtodeterminethevalue. Forinstance: @var:0; .class{ @var:1; .brass{ @var:2; three:@var; @var:3; } one:@var; } Compilesto: .class{ one:1; } .class.brass{ three:3; } Essentially,eachscopehasa"final"value,similartopropertiesinthebrowser,likethisexampleusingcustomproperties: .header{ --color:white; color:var(--color);//thecolorisblack --color:black; } Thismeansthat,unlikeotherCSSpre-processinglanguages,LessvariablesbehaveverymuchlikeCSS's. PropertiesasVariables(NEW!) v3.0.0 Youcaneasilytreatpropertieslikevariablesusingthe$propsyntax.Sometimesthiscan makeyourcodealittlelighter. .widget{ color:#efefef; background-color:$color; } Compilesto: .widget{ color:#efefef; background-color:#efefef; } Notethat,likevariables,Lesswillchoosethelastpropertywithinthecurrent/parentscope asbeingthe"final"value. .block{ color:red; .inner{ background-color:$color; } color:blue; } Compilesto: .block{ color:red; color:blue; } .block.inner{ background-color:blue; } DefaultVariables Wesometimesgetrequestsfordefaultvariables-anabilitytosetavariableonlyifitisnotalreadyset.Thisfeatureisnotrequiredbecauseyoucaneasilyoverrideavariablebyputtingthedefinitionafterwards. Forinstance: //library @base-color:green; @dark-color:darken(@base-color,10%); //useoflibrary @import"library.less"; @base-color:red; ThisworksfinebecauseofLazyLoading-@base-colorisoverriddenand@dark-colorisadarkred. ParentSelectors Editthemarkdownsourcefor"parent-selectors" Referencingparentselectorswith& The&operatorrepresentstheparentselectorsofanestedruleandismostcommonlyusedwhenapplyingamodifyingclassorpseudo-classtoanexistingselector: a{ color:blue; &:hover{ color:green; } } resultsin: a{ color:blue; } a:hover{ color:green; } Noticethatwithoutthe&,theaboveexamplewouldresultina:hoverrule(adescendantselectorthatmatcheshoveredelementsinsideoftags)andthisisnotwhatwetypicallywouldwantwiththenested:hover. The"parentselectors"operatorhasavarietyofuses.Basicallyanytimeyouneedtheselectorsofthenestedrulestobecombinedinotherwaysthanthedefault.Forexampleanothertypicaluseofthe&istoproducerepetitiveclassnames: .button{ &-ok{ background-image:url("ok.png"); } &-cancel{ background-image:url("cancel.png"); } &-custom{ background-image:url("custom.png"); } } output: .button-ok{ background-image:url("ok.png"); } .button-cancel{ background-image:url("cancel.png"); } .button-custom{ background-image:url("custom.png"); } Multiple& &mayappearmorethanoncewithinaselector.Thismakesitpossibletorepeatedlyrefertoaparentselectorwithoutrepeatingitsname. .link{ &+&{ color:red; } &&{ color:green; } &&{ color:blue; } &,&ish{ color:cyan; } } willoutput: .link+.link{ color:red; } .link.link{ color:green; } .link.link{ color:blue; } .link,.linkish{ color:cyan; } Notethat&representsallparentselectors(notjustthenearestancestor)sothefollowingexample: .grand{ .parent{ &>&{ color:red; } &&{ color:green; } &&{ color:blue; } &,&ish{ color:cyan; } } } resultsin: .grand.parent>.grand.parent{ color:red; } .grand.parent.grand.parent{ color:green; } .grand.parent.grand.parent{ color:blue; } .grand.parent, .grand.parentish{ color:cyan; } ChangingSelectorOrder Itcanbeusefultoprependaselectortotheinherited(parent)selectors.Thiscanbedonebyputtingthe&aftercurrentselector. Forexample,whenusingModernizr,youmightwanttospecifydifferentrulesbasedonsupportedfeatures: .header{ .menu{ border-radius:5px; .no-borderradius&{ background-image:url('images/button-background.png'); } } } Theselector.no-borderradius&willprepend.no-borderradiustoitsparent.header.menutoformthe.no-borderradius.header.menuonoutput: .header.menu{ border-radius:5px; } .no-borderradius.header.menu{ background-image:url('images/button-background.png'); } CombinatorialExplosion &canalsobeusedtogenerateeverypossiblepermutationofselectorsinacommaseparatedlist: p,a,ul,li{ border-top:2pxdotted#366; &+&{ border-top:0; } } Thisexpandstoallpossible(16)combinationsofthespecifiedelements: p, a, ul, li{ border-top:2pxdotted#366; } p+p, p+a, p+ul, p+li, a+p, a+a, a+ul, a+li, ul+p, ul+a, ul+ul, ul+li, li+p, li+a, li+ul, li+li{ border-top:0; } Extend Editthemarkdownsourcefor"extend" ExtendisaLesspseudo-classwhichmergestheselectoritisputonwithonesthatmatchwhatitreferences. Releasedv1.4.0 navul{ &:extend(.inline); background:blue; } Intherulesetabove,the:extendselectorwillapplythe"extendingselector"(navul)ontothe.inlineclasswhereverthe.inlineclassappears.Thedeclarationblockwillbekeptas-is,butwithoutanyreferencetotheextend(becauseextendisn'tcss). Sothefollowing: navul{ &:extend(.inline); background:blue; } .inline{ color:red; } Outputs navul{ background:blue; } .inline, navul{ color:red; } Noticehowthenavul:extend(.inline)selectorgetsoutputasnavul-theextendgetsremovedbeforeoutputandtheselectorblockleftas-is.Ifnopropertiesareputinthatblockthenitgetsremovedfromtheoutput(buttheextendstillmayaffectotherselectors). ExtendSyntax Theextendiseitherattachedtoaselectororplacedintoaruleset.Itlookslikeapseudo-classwithselectorparameteroptionallyfollowedbythekeywordall: Example: .a:extend(.b){} //theaboveblockdoesthesamethingasthebelowblock .a{ &:extend(.b); } .c:extend(.dall){ //extendsallinstancesof".d"e.g.".x.d"or".d.x" } .c:extend(.d){ //extendsonlyinstanceswheretheselectorwillbeoutputasjust".d" } Itcancontainoneormoreclassestoextend,separatedbycommas. Example: .e:extend(.f){} .e:extend(.g){} //theaboveandthebelowdothesamething .e:extend(.f,.g){} ExtendAttachedtoSelector Extendattachedtoaselectorlookslikeanordinarypseudo-classwithselectorasaparameter.Aselectorcancontainmultipleextendclauses,butallextendsmustbeattheendoftheselector. Extendaftertheselector:pre:hover:extend(divpre). Spacebetweenselectorandextendisallowed:pre:hover:extend(divpre). Multipleextendsareallowed:pre:hover:extend(divpre):extend(.buckettr)-Notethisisthesameaspre:hover:extend(divpre,.buckettr) ThisisNOTallowed:pre:hover:extend(divpre).nth-child(odd).Extendmustbelast. Ifarulesetcontainsmultipleselectors,anyofthemcanhavetheextendkeyword.Multipleselectorswithextendinoneruleset: .big-division, .big-bag:extend(.bag), .big-bucket:extend(.bucket){ //body } ExtendInsideRuleset Extendcanbeplacedintoaruleset'sbodyusing&:extend(selector)syntax.Placingextendintoabodyisashortcutforplacingitintoeverysingleselectorofthatruleset. Extendinsideabody: pre:hover, .some-class{ &:extend(divpre); } isexactlythesameasaddinganextendaftereachselector: pre:hover:extend(divpre), .some-class:extend(divpre){} ExtendingNestedSelectors Extendisabletomatchnestedselectors.Followingless: Example: .bucket{ tr{//nestedrulesetwithtargetselector color:blue; } } .some-class:extend(.buckettr){}//nestedrulesetisrecognized Outputs .buckettr, .some-class{ color:blue; } Essentiallytheextendlooksatthecompiledcss,nottheoriginalless. Example: .bucket{ tr&{//nestedrulesetwithtargetselector color:blue; } } .some-class:extend(tr.bucket){}//nestedrulesetisrecognized Outputs tr.bucket, .some-class{ color:blue; } ExactMatchingwithExtend Extendbydefaultlooksforexactmatchbetweenselectors.Itdoesmatterwhetherselectorusesleadingstarornot.Itdoesnotmatterthattwonth-expressionshavethesamemeaning,theyneedtohavetosameforminordertobematched.Theonlyexceptionarequotesinattributeselector,lessknowstheyhavethesamemeaningandmatchesthem. Example: .a.class, .class.a, .class>.a{ color:blue; } .test:extend(.class){}//thiswillNOTmatchtheanyselectorsabove Leadingstardoesmatter.Selectors*.classand.classareequivalent,butextendwillnotmatchthem: *.class{ color:blue; } .noStar:extend(.class){}//thiswillNOTmatchthe*.classselector Outputs *.class{ color:blue; } Orderofpseudo-classesdoesmatter.Selectorslink:hover:visitedandlink:visited:hovermatchthesamesetofelements,butextendtreatsthemasdifferent: link:hover:visited{ color:blue; } .selector:extend(link:visited:hover){} Outputs link:hover:visited{ color:blue; } nthExpression Nthexpressionformdoesmatter.Nth-expressions1n+3andn+3areequivalent,butextendwillnotmatchthem: :nth-child(1n+3){ color:blue; } .child:extend(:nth-child(n+3)){} Outputs :nth-child(1n+3){ color:blue; } Quotetypeinattributeselectordoesnotmatter.Allofthefollowingareequivalent. [title=identifier]{ color:blue; } [title='identifier']{ color:blue; } [title="identifier"]{ color:blue; } .noQuote:extend([title=identifier]){} .singleQuote:extend([title='identifier']){} .doubleQuote:extend([title="identifier"]){} Outputs [title=identifier], .noQuote, .singleQuote, .doubleQuote{ color:blue; } [title='identifier'], .noQuote, .singleQuote, .doubleQuote{ color:blue; } [title="identifier"], .noQuote, .singleQuote, .doubleQuote{ color:blue; } Extend"all" WhenyouspecifytheallkeywordlastinanextendargumentittellsLesstomatchthatselectoraspartofanotherselector.Theselectorwillbecopiedandthematchedpartoftheselectoronlywillthenbereplacedwiththeextend,makinganewselector. Example: .a.b.test, .test.c{ color:orange; } .test{ &:hover{ color:green; } } .replacement:extend(.testall){} Outputs .a.b.test, .test.c, .a.b.replacement, .replacement.c{ color:orange; } .test:hover, .replacement:hover{ color:green; } Youcanthinkofthismodeofoperationasessentiallydoinganon-destructivesearchandreplace. SelectorInterpolationwithExtend Extendisnotabletomatchselectorswithvariables.Ifselectorcontainsvariable,extendwillignoreit. However,extendcanbeattachedtointerpolatedselector. Selectorwithvariablewillnotbematched: @variable:.bucket; @{variable}{//interpolatedselector color:blue; } .some-class:extend(.bucket){}//doesnothing,nomatchisfound andextendwithvariableintargetselectormatchesnothing: .bucket{ color:blue; } .some-class:extend(@{variable}){}//interpolatedselectormatchesnothing @variable:.bucket; Bothoftheaboveexamplescompileinto: .bucket{ color:blue; } However,:extendattachedtoaninterpolatedselectorworks: .bucket{ color:blue; } @{variable}:extend(.bucket){} @variable:.selector; compilesto: .bucket,.selector{ color:blue; } Scoping/ExtendInside@media Currently,an:extendinsidea@mediadeclarationwillonlymatchselectorsinsidethesamemediadeclaration: @mediaprint{ .screenClass:extend(.selector){}//extendinsidemedia .selector{//thiswillbematched-itisinthesamemedia color:black; } } .selector{//rulesetontopofstylesheet-extendignoresit color:red; } @mediascreen{ .selector{//rulesetinsideanothermedia-extendignoresit color:blue; } } compilesinto: @mediaprint{ .selector, .screenClass{/*rulesetinsidethesamemediawasextended*/ color:black; } } .selector{/*rulesetontopofstylesheetwasignored*/ color:red; } @mediascreen{ .selector{/*rulesetinsideanothermediawasignored*/ color:blue; } } Note:extendingdoesnotmatchselectorsinsideanested@mediadeclaration: @mediascreen{ .screenClass:extend(.selector){}//extendinsidemedia @media(min-width:1023px){ .selector{//rulesetinsidenestedmedia-extendignoresit color:blue; } } } Thiscompilesinto: @mediascreenand(min-width:1023px){ .selector{/*rulesetinsideanothernestedmediawasignored*/ color:blue; } } Toplevelextendmatcheseverythingincludingselectorsinsidenestedmedia: @mediascreen{ .selector{/*rulesetinsidenestedmedia-toplevelextendworks*/ color:blue; } @media(min-width:1023px){ .selector{/*rulesetinsidenestedmedia-toplevelextendworks*/ color:blue; } } } .topLevel:extend(.selector){}/*toplevelextendmatcheseverything*/ compilesinto: @mediascreen{ .selector, .topLevel{/*rulesetinsidemediawasextended*/ color:blue; } } @mediascreenand(min-width:1023px){ .selector, .topLevel{/*rulesetinsidenestedmediawasextended*/ color:blue; } } DuplicationDetection Currentlythereisnoduplicationdetection. Example: .alert-info, .widget{ /*declarations*/ } .alert:extend(.alert-info,.widget){} Outputs .alert-info, .widget, .alert, .alert{ /*declarations*/ } UseCasesforExtend ClassicUseCase Theclassicusecaseistoavoidaddingabaseclass.Forexample,ifyouhave .animal{ background-color:black; color:white; } andyouwanttohaveasubtypeofanimalwhichoverridesthebackgroundcolorthenyouhavetwooptions,firstlychangeyourHTML Bear .animal{ background-color:black; color:white; } .bear{ background-color:brown; } orhavesimplifiedhtmlanduseextendinyourless.e.g. Bear .animal{ background-color:black; color:white; } .bear{ &:extend(.animal); background-color:brown; } ReducingCSSSize Mixinscopyallofthepropertiesintoaselector,whichcanleadtounnecessaryduplication.Thereforeyoucanuseextendsinsteadofmixinstomovetheselectoruptothepropertiesyouwishtouse,whichleadstolessCSSbeinggenerated. Example-withmixin: .my-inline-block(){ display:inline-block; font-size:0; } .thing1{ .my-inline-block; } .thing2{ .my-inline-block; } Outputs .thing1{ display:inline-block; font-size:0; } .thing2{ display:inline-block; font-size:0; } Example(withextends): .my-inline-block{ display:inline-block; font-size:0; } .thing1{ &:extend(.my-inline-block); } .thing2{ &:extend(.my-inline-block); } Outputs .my-inline-block, .thing1, .thing2{ display:inline-block; font-size:0; } CombiningStyles/AMoreAdvancedMixin Anotheruse-caseisasanalternativeforamixin-becausemixinscanonlybeusedwithsimpleselectors,ifyouhavetwodifferentblocksofhtml,butneedtoapplythesamestylestobothyoucanuseextendstorelatetwoareas. Example: li.list>a{ //liststyles } button.list-style{ &:extend(li.list>a);//usethesameliststyles } Merge Editthemarkdownsourcefor"merge" Combineproperties Themergefeatureallowsforaggregatingvaluesfrommultiplepropertiesintoacommaorspaceseparatedlistunderasingleproperty.mergeisusefulforpropertiessuchasbackgroundandtransform. Comma Appendpropertyvaluewithcomma Releasedv1.5.0 Example: .mixin(){ box-shadow+:inset0010px#555; } .myclass{ .mixin(); box-shadow+:0020pxblack; } Outputs .myclass{ box-shadow:inset0010px#555,0020pxblack; } Space Appendpropertyvaluewithspace Releasedv1.7.0 Example: .mixin(){ transform+_:scale(2); } .myclass{ .mixin(); transform+_:rotate(15deg); } Outputs .myclass{ transform:scale(2)rotate(15deg); } Toavoidanyunintentionaljoins,mergerequiresanexplicit+or+_flagoneachjoinpendingdeclaration. Mixins Editthemarkdownsourcefor"mixins" "mix-in"propertiesfromexistingstyles Youcanmix-inclassselectorsandidselectors,e.g. .a,#b{ color:red; } .mixin-class{ .a(); } .mixin-id{ #b(); } whichresultsin: .a,#b{ color:red; } .mixin-class{ color:red; } .mixin-id{ color:red; } Currentlyandhistorically,theparenthesesinamixincallareoptional,butoptionalparenthesesaredeprecatedandwillberequiredinafuturerelease. .a(); .a;//currentlyworks,butdeprecated;don'tuse NotOutputtingtheMixin IfyouwanttocreateamixinbutyoudonotwantthatmixintobeinyourCSSoutput,putparenthesesafterthemixindefinition. .my-mixin{ color:black; } .my-other-mixin(){ background:white; } .class{ .my-mixin(); .my-other-mixin(); } outputs .my-mixin{ color:black; } .class{ color:black; background:white; } SelectorsinMixins Mixinscancontainmorethanjustproperties,theycancontainselectorstoo. Forexample: .my-hover-mixin(){ &:hover{ border:1pxsolidred; } } button{ .my-hover-mixin(); } Outputs button:hover{ border:1pxsolidred; } Namespaces Ifyouwanttomixinpropertiesinsideamorecomplicatedselector,youcanstackupmultipleid'sorclasses. #outer(){ .inner{ color:red; } } .c{ #outer>.inner(); } Both>andwhitespaceareoptional //alldothesamething #outer>.inner(); #outer.inner(); #outer.inner(); Namespacingyourmixinslikereducesconflictwithotherlibrarymixinsorusermixins,butitcanalsobeawayto"organize"groupsofmixins. Example: #my-library{ .my-mixin(){ color:black; } } //whichcanbeusedlikethis .class{ #my-library.my-mixin(); } GuardedNamespaces Ifanamespacehasaguard,mixinsdefinedbyitareusedonlyiftheguardconditionreturnstrue.Anamespaceguardisevaluatedexactlythesamewayasaguardonmixin,sothefollowingtwomixinsworkthesameway: #namespacewhen(@mode=huge){ .mixin(){/**/} } #namespace{ .mixin()when(@mode=huge){/**/} } Thedefaultfunctionisassumedtohavethesamevalueforallnestednamespacesandmixin.Followingmixinisneverevaluated,oneofitsguardsisguaranteedtobefalse: #sp_1when(default()){ #sp_2when(default()){ .mixin()whennot(default()){/**/} } } The!importantkeyword Usethe!importantkeywordaftermixincalltomarkallpropertiesinheritedbyitas!important: Example: .foo(@bg:#f5f5f5,@color:#900){ background:@bg; color:@color; } .unimportant{ .foo(); } .important{ .foo()!important; } Resultsin: .unimportant{ background:#f5f5f5; color:#900; } .important{ background:#f5f5f5!important; color:#900!important; } ParametricMixins Editthemarkdownsourcefor"mixins-parametric" Howtopassargumentstomixins Mixinscanalsotakearguments,whicharevariablespassedtotheblockofselectorswhenitismixedin. Forexample: .border-radius(@radius){ -webkit-border-radius:@radius; -moz-border-radius:@radius; border-radius:@radius; } Andhere'showwecanmixitintovariousrulesets: #header{ .border-radius(4px); } .button{ .border-radius(6px); } Parametricmixinscanalsohavedefaultvaluesfortheirparameters: .border-radius(@radius:5px){ -webkit-border-radius:@radius; -moz-border-radius:@radius; border-radius:@radius; } Wecaninvokeitlikethisnow: #header{ .border-radius(); } Anditwillincludea5pxborder-radius. Youcanalsouseparametricmixinswhichdon'ttakeparameters.ThisisusefulifyouwanttohidetherulesetfromtheCSSoutput,butwanttoincludeitspropertiesinotherrulesets: .wrap(){ text-wrap:wrap; white-space:-moz-pre-wrap; white-space:pre-wrap; word-wrap:break-word; } pre{.wrap()} Whichwouldoutput: pre{ text-wrap:wrap; white-space:-moz-pre-wrap; white-space:pre-wrap; word-wrap:break-word; } MixinswithMultipleParameters Parametersareeithersemicolonorcommaseparated.Itisrecommendedtousesemicolon.Thesymbolcommahasdoublemeaning:itcanbeinterpretedeitherasamixinparametersseparatororcsslistseparator. Usingcommaasmixinseparatormakesitimpossibletocreatecommaseparatedlistsasanargument.Ontheotherhand,ifthecompilerseesatleastonesemicoloninsidemixincallordeclaration,itassumesthatargumentsareseparatedbysemicolonsandallcommasbelongtocsslists: twoargumentsandeachcontainscommaseparatedlist:.name(1,2,3;something,else), threeargumentsandeachcontainsonenumber:.name(1,2,3), usedummysemicolontocreatemixincallwithoneargumentcontainingcommaseparatedcsslist:.name(1,2,3;), commaseparateddefaultvalue:.name(@param1:red,blue;). Itislegaltodefinemultiplemixinswiththesamenameandnumberofparameters.Lesswillusepropertiesofallthatcanapply.Ifyouusedthemixinwithoneparametere.g..mixin(green);,thenpropertiesofallmixinswithexactlyonemandatoryparameterwillbeused: .mixin(@color){ color-1:@color; } .mixin(@color;@padding:2){ color-2:@color; padding-2:@padding; } .mixin(@color;@padding;@margin:2){ color-3:@color; padding-3:@padding; margin:@margin@margin@margin@margin; } .some.selectordiv{ .mixin(#008000); } compilesinto: .some.selectordiv{ color-1:#008000; color-2:#008000; padding-2:2; } NamedParameters Amixinreferencecansupplyparametersvaluesbytheirnamesinsteadofjustpositions.Anyparametercanbereferencedbyitsnameandtheydonothavetobeinanyspecialorder: .mixin(@color:black;@margin:10px;@padding:20px){ color:@color; margin:@margin; padding:@padding; } .class1{ .mixin(@margin:20px;@color:#33acfe); } .class2{ .mixin(#efca44;@padding:40px); } compilesinto: .class1{ color:#33acfe; margin:20px; padding:20px; } .class2{ color:#efca44; margin:10px; padding:40px; } The@argumentsVariable @argumentshasaspecialmeaninginsidemixins,itcontainsalltheargumentspassed,whenthemixinwascalled.Thisisusefulifyoudon'twanttodealwithindividualparameters: .box-shadow(@x:0;@y:0;@blur:1px;@color:#000){ -webkit-box-shadow:@arguments; -moz-box-shadow:@arguments; box-shadow:@arguments; } .big-block{ .box-shadow(2px;5px); } Whichresultsin: .big-block{ -webkit-box-shadow:2px5px1px#000; -moz-box-shadow:2px5px1px#000; box-shadow:2px5px1px#000; } AdvancedArgumentsandthe@restVariable Youcanuse...ifyouwantyourmixintotakeavariablenumberofarguments.Usingthisafteravariablenamewillassignthoseargumentstothevariable. .mixin(...){//matches0-Narguments .mixin(){//matchesexactly0arguments .mixin(@a:1){//matches0-1arguments .mixin(@a:1;...){//matches0-Narguments .mixin(@a;...){//matches1-Narguments Furthermore: .mixin(@a;@rest...){ //@restisboundtoargumentsafter@a //@argumentsisboundtoallarguments } Pattern-matching Sometimes,youmaywanttochangethebehaviorofamixin,basedontheparametersyoupasstoit.Let'sstartwithsomethingbasic: .mixin(@s;@color){...} .class{ .mixin(@switch;#888); } Nowlet'ssaywewant.mixintobehavedifferently,basedonthevalueof@switch,wecoulddefine.mixinassuch: .mixin(dark;@color){ color:darken(@color,10%); } .mixin(light;@color){ color:lighten(@color,10%); } .mixin(@_;@color){ display:block; } Now,ifwerun: @switch:light; .class{ .mixin(@switch;#888); } WewillgetthefollowingCSS: .class{ color:#a2a2a2; display:block; } Wherethecolorpassedto.mixinwaslightened.Ifthevalueof@switchwasdark, theresultwouldbeadarkercolor. Here'swhathappened: Thefirstmixindefinitiondidn'tmatchbecauseitexpecteddarkasthefirstargument. Thesecondmixindefinitionmatched,becauseitexpectedlight. Thethirdmixindefinitionmatchedbecauseitexpectedanyvalue. Onlymixindefinitionswhichmatchedwereused.Variablesmatchandbindtoanyvalue. Anythingotherthanavariablematchesonlywithavalueequaltoitself. Wecanalsomatchonarity,here'sanexample: .mixin(@a){ color:@a; } .mixin(@a;@b){ color:fade(@a;@b); } Nowifwecall.mixinwithasingleargument,wewillgettheoutputofthefirstdefinition, butifwecallitwithtwoarguments,wewillgettheseconddefinition,namely@afadedto@b. UsingMixinsasFunctions Editthemarkdownsourcefor"mixins-as-functions" Selectingpropertiesandvariablesfrommixincalls Property/valueaccessors Releasedv3.5.0 StartinginLess3.5,youcanuseproperty/variableaccessorstoselectavaluefromanevaluatedmixin'srules.Thiscanallowyoutousemixinssimilartofunctions. Example: .average(@x,@y){ @result:((@x+@y)/2); } div{ //callamixinandlookupits"@result"value padding:.average(16px,50px)[@result]; } Resultsin: div{ padding:33px; } Overridingmixinvalues Ifyouhavemultiplematchingmixins,allrulesareevaluatedandmerged,andthelastmatchingvaluewiththatidentifierisreturned.ThisissimilartothecascadeinCSS,anditallowsyouto"override"mixinvalues. //library.less #library(){ .mixin(){ prop:foo; } } //customize.less @import"library"; #library(){ .mixin(){ prop:bar; } } .box{ my-value:#library.mixin[prop]; } Outputs: .box{ my-value:bar; } Unnamedlookups Ifyoudon'tspecifyalookupvaluein[@lookup]andinsteadwrite[]afteramixinorrulesetcall,allvalueswillcascadeandthelastdeclaredvaluewillbeselected. Meaning:theaveragingmixinfromtheaboveexamplecouldbewrittenas: .average(@x,@y){ @result:((@x+@y)/2); } div{ //callamixinandlookupitsfinalvalue padding:.average(16px,50px)[]; } Theoutputisthesame: div{ padding:33px; } Thesamecascadingbehavioristrueforrulesetsorvariablesaliasedtomixincalls. @dr:{ value:foo; } .box{ my-value:@dr[]; } Thisoutputs: .box{ my-value:foo; } Unlockingmixins&variablesintocallerscope DEPRECATED-UseProperty/ValueAccessors Variablesandmixinsdefinedinamixinarevisibleandcanbeusedincaller'sscope.Thereisonlyoneexception:avariableisnotcopiedifthecallercontainsavariablewiththesamename(thatincludesvariablesdefinedbyanothermixincall).Onlyvariablespresentincallerslocalscopeareprotected.Variablesinheritedfromparentscopesareoverridden. Note:thisbehaviorisdeprecated,andinthefuture,variablesandmixinswillnotbemergedintothecallerscopeinthisway. Example: .mixin(){ @width:100%; @height:200px; } .caller{ .mixin(); width:@width; height:@height; } Resultsin: .caller{ width:100%; height:200px; } Variablesdefineddirectlyincallersscopecannotbeoverridden.However,variablesdefinedincallersparentscopeisnotprotectedandwillbeoverridden: .mixin(){ @size:in-mixin; @definedOnlyInMixin:in-mixin; } .class{ margin:@size@definedOnlyInMixin; .mixin(); } @size:globaly-defined-value;//callersparentscope-noprotection Resultsin: .class{ margin:in-mixinin-mixin; } Finally,mixindefinedinmixinactsasreturnvaluetoo: .unlock(@value){//outermixin .doSomething(){//nestedmixin declaration:@value; } } #namespace{ .unlock(5);//unlockdoSomethingmixin .doSomething();//nestedmixinwascopiedhereandisusable } Resultsin: #namespace{ declaration:5; } RecursiveMixins Editthemarkdownsourcefor"mixin-loops" Creatingloops InLessamixincancallitself.Suchrecursivemixins,whencombinedwithGuardExpressionsandPatternMatching,canbeusedtocreatevariousiterative/loopstructures. Example: .loop(@counter)when(@counter>0){ .loop((@counter-1));//nextiteration width:(10px*@counter);//codeforeachiteration } div{ .loop(5);//launchtheloop } Output: div{ width:10px; width:20px; width:30px; width:40px; width:50px; } AgenericexampleofusingarecursivelooptogenerateCSSgridclasses: .generate-columns(4); .generate-columns(@n,@i:1)when(@i==50%){ background-color:black; } .mixin(@a)when(lightness(@a)<50%){ background-color:white; } .mixin(@a){ color:@a; } Thekeyisthewhenkeyword,whichintroducesaguardsequence(herewithonlyoneguard).Nowifwerunthefollowingcode: .class1{.mixin(#ddd)} .class2{.mixin(#555)} Here'swhatwe'llget: .class1{ background-color:black; color:#ddd; } .class2{ background-color:white; color:#555; } GuardComparisonOperators Thefulllistofcomparisonoperatorsusableinguardsare:>,>=,=,=@b){width:@a} .max(@a;@b)when(@a0){...} Youcanemulatetheoroperatorbyseparatingguardswithacomma,.Ifanyoftheguardsevaluatetotrue,it'sconsideredamatch: .mixin(@a)when(@a>10),(@a0){...} TypeCheckingFunctions Lastly,ifyouwanttomatchmixinsbasedonvaluetype,youcanusetheisfunctions: .mixin(@a;@b:0)when(isnumber(@b)){...} .mixin(@a;@b:black)when(iscolor(@b)){...} Herearethebasictypecheckingfunctions: iscolor isnumber isstring iskeyword isurl Ifyouwanttocheckifavalueisinaspecificunitinadditiontobeinganumber,youmayuseoneof: ispixel ispercentage isem isunit AliasingMixins Editthemarkdownsourcefor"mixins-aliasing" Releasedv3.5.0 Assigningmixincallstoavariable Mixinscanbeassignedtoavariabletobecalledasavariablecall,orcanbeusedformaplookup. #theme.dark.navbar{ .colors(light){ primary:purple; } .colors(dark){ primary:black; secondary:grey; } } .navbar{ @colors:#theme.dark.navbar.colors(dark); background:@colors[primary]; border:1pxsolid@colors[secondary]; } Thiswouldoutput: .navbar{ background:black; border:1pxsolidgrey; } Variablecalls Entiremixincallscanbealiasedandcalledasvariablecalls.Asin: #library(){ .rules(){ background:green; } } .box{ @alias:#library.rules(); @alias(); } Outputs: .box{ background:green; } Note,unlikemixinsusedinroot,mixincallsassignedtovariablesandcalledwithnoargumentsalwaysrequireparentheses.Thefollowingisnotvalid. #library(){ .rules(){ background:green; } } .box{ @alias:#library.colors; @alias();//ERROR:Couldnotevaluatevariablecall@alias } Thisisbecauseit'sambiguousifvariableisassignedalistofselectorsoramixincall.Forexample,inLess3.5+,thisvariablecouldbeusedthisway. .box{ @alias:#library.colors; @{alias}{ a:b; } } Theabovewouldoutput: .box#library.colors{ a:b; } CSSGuards Editthemarkdownsourcefor"css-guards" "if"'saroundselectors Releasedv1.5.0 LikeMixinGuards,guardscanalsobeappliedtocssselectors,whichissyntacticsugarfordeclaringthemixinandthencallingitimmediately. Forinstance,before1.5.0youwouldhavehadtodothis: .my-optional-style()when(@my-option=true){ button{ color:white; } } .my-optional-style(); Now,youcanapplytheguarddirectlytoastyle. buttonwhen(@my-option=true){ color:white; } Youcanalsoachieveaniftypestatementbycombiningthiswiththe&feature,allowingyoutogroupmultipleguards. &when(@my-option=true){ button{ color:white; } a{ color:blue; } } Notethatyoucanalsoachieveasimilarpatternbyusingtheactualif()functionandavariablecall.Asin: @dr:if(@my-option=true,{ button{ color:white; } a{ color:blue; } }); @dr(); DetachedRulesets Editthemarkdownsourcefor"detached-rulesets" Assignarulesettoavariable Releasedv1.7.0 Adetachedrulesetisagroupofcssproperties,nestedrulesets,mediadeclarationsoranythingelsestoredinavariable.Youcanincludeitintoarulesetoranotherstructureandallitspropertiesaregoingtobecopiedthere.Youcanalsouseitasamixinargumentandpassitaroundasanyothervariable. Simpleexample: //declaredetachedruleset @detached-ruleset:{background:red;};//semi-colonisoptionalin3.5.0+ //usedetachedruleset .top{ @detached-ruleset(); } compilesinto: .top{ background:red; } Parenthesesafteradetachedrulesetcallaremandatory(exceptwhenfollowedbyalookupvalue).Thecall@detached-ruleset;wouldnotwork. Itisusefulwhenyouwanttodefineamixinthatabstractsouteitherwrappingapieceofcodeinamediaqueryoranon-supportedbrowserclassname.Therulesetscanbepassedtomixinsothatthemixincanwrapthecontent,e.g. .desktop-and-old-ie(@rules){ @mediascreenand(min-width:1200px){@rules();} html.lt-ie9&{@rules();} } header{ background-color:blue; .desktop-and-old-ie({ background-color:red; }); } Herethedesktop-and-old-iemixindefinesthemediaqueryandrootclasssothatyoucanuseamixintowrapapieceofcode.Thiswilloutput header{ background-color:blue; } @mediascreenand(min-width:1200px){ header{ background-color:red; } } html.lt-ie9header{ background-color:red; } ArulesetcanbenowassignedtoavariableorpassedintoamixinandcancontainthefullsetofLessfeatures,e.g. @my-ruleset:{ .my-selector{ background-color:black; } }; Youcaneventakeadvantageofmediaquerybubbling,forinstance @my-ruleset:{ .my-selector{ @mediatv{ background-color:black; } } }; @media(orientation:portrait){ @my-ruleset(); } whichwilloutput @media(orientation:portrait)andtv{ .my-selector{ background-color:black; } } Adetachedrulesetcallunlocks(returns)allitsmixinsintocallerthesamewayasmixincallsdo.However,itdoesnotreturnvariables. Returnedmixin: //detachedrulesetwithamixin @detached-ruleset:{ .mixin(){ color:blue; } }; //calldetachedruleset .caller{ @detached-ruleset(); .mixin(); } Resultsin: .caller{ color:blue; } Privatevariables: @detached-ruleset:{ @color:blue;//thisvariableisprivate }; .caller{ color:@color;//syntaxerror } Scoping Adetachedrulesetcanuseallvariablesandmixinsaccessiblewhereitisdefinedandwhereitiscalled.Otherwisesaid,bothdefinitionandcallerscopesareavailabletoit.Ifbothscopescontainsthesamevariableormixin,declarationscopevaluetakesprecedence. Declarationscopeistheonewheredetachedrulesetbodyisdefined.Copyingadetachedrulesetfromonevariableintoanothercannotmodifyitsscope.Therulesetdoesnotgainaccesstonewscopesjustbybeingreferencedthere. Lastly,adetachedrulesetcangainaccesstoscopebybeingunlocked(imported)intoit. Note:unlockingvariablesintoscopeviaacalledmixinisdeprecated.Useproperty/variableaccessors. DefinitionandCallerScopeVisibility Adetachedrulesetseesthecaller'svariablesandmixins: @detached-ruleset:{ caller-variable:@caller-variable;//variableisundefinedhere .caller-mixin();//mixinisundefinedhere }; selector{ //usedetachedruleset @detached-ruleset(); //definevariableandmixinneededinsidethedetachedruleset @caller-variable:value; .caller-mixin(){ variable:declaration; } } compilesinto: selector{ caller-variable:value; variable:declaration; } Variableandmixinsaccessiblefromdefinitionwinoverthoseavailableinthecaller: @variable:global; @detached-ruleset:{ //willuseglobalvariable,becauseitisaccessible //fromdetached-rulesetdefinition variable:@variable; }; selector{ @detached-ruleset(); @variable:value;//variabledefinedincaller-willbeignored } compilesinto: selector{ variable:global; } ReferencingWon'tModifyDetachedRulesetScope Arulesetdoesnotgainaccesstonewscopesjustbybeingreferencedthere: @detached-1:{scope-detached:@one@two;}; .one{ @one:visible; .two{ @detached-2:@detached-1;//copying/renamingruleset @two:visible;//rulesetcannotseethisvariable } } .use-place{ .one>.two(); @detached-2(); } throwsanerror: ERROR1:32Thevariable"@one"wasnotdeclared. UnlockingWillModifyDetachedRulesetScope Adetachedrulesetgainsaccessbybeingunlocked(imported)insideascope: #space{ .importer-1(){ @detached:{scope-detached:@variable;};//definedetachedruleset } } .importer-2(){ @variable:value;//unlockeddetachedrulesetCANseethisvariable #space>.importer-1();//unlock/importdetachedruleset } .use-place{ .importer-2();//unlock/importdetachedrulesetsecondtime @detached(); } compilesinto: .use-place{ scope-detached:value; } Property/variableaccessors (Lookupvalues) Releasedv3.5.0 StartinginLess3.5,youcanuseproperty/variableaccessors(alsocalled"lookups")toselectavaluefromvariable(detached)rulesets. @config:{ option1:true; option2:false; } .mixin()when(@config[option1]=true){ selected:value; } .box{ .mixin(); } Outputs: .box{ selected:value; } Ifwhatisreturnedfromalookupisanotherdetachedruleset,youcanuseasecondlookuptogetthatvalue. @config:{ @colors:{ primary:blue; } } .box{ color:@config[@colors][primary]; } Variablevariablesinlookups Thelookupvaluethatisreturnedcanitselfbevariable.Asin,youcanwrite: @config:{ @dark:{ primary:darkblue; } @light:{ primary:lightblue; } } .box{ @lookup:dark; color:@config[@@lookup][primary]; } Thiswilloutput: .box{ color:darkblue; } @importAt-Rules Editthemarkdownsourcefor"imports" Importstylesfromotherstylesheets InstandardCSS,@importat-rulesmustprecedeallothertypesofrules.ButLessdoesn'tcarewhereyouput@importstatements. Example: .foo{ background:#900; } @import"this-is-valid.less"; FileExtensions @importstatementsmaybetreateddifferentlybyLessdependingonthefileextension: Ifthefilehasa.cssextensionitwillbetreatedasCSSandthe@importstatementleftas-is(seetheinlineoptionbelow). IfithasanyotherextensionitwillbetreatedasLessandimported. Ifitdoesnothaveanextension,.lesswillbeappendedanditwillbeincludedasaimportedLessfile. Examples: @import"foo";//foo.lessisimported @import"foo.less";//foo.lessisimported @import"foo.php";//foo.phpimportedasaLessfile @import"foo.css";//statementleftinplace,as-is Thefollowingoptionscanbeusedtooverridethisbehavior. ImportOptions LessoffersseveralextensionstotheCSS@importCSSat-ruletoprovidemoreflexibilityoverwhatyoucandowithexternalfiles. Syntax:@import(keyword)"filename"; Thefollowingimportoptionshavebeenimplemented: reference:useaLessfilebutdonotoutputit inline:includethesourcefileintheoutputbutdonotprocessit less:treatthefileasaLessfile,nomatterwhatthefileextension css:treatthefileasaCSSfile,nomatterwhatthefileextension once:onlyincludethefileonce(thisisdefaultbehavior) multiple:includethefilemultipletimes optional:continuecompilingwhenfileisnotfound Morethanonekeywordper@importisallowed,youwillhavetousecommastoseparatethekeywords: Example:@import(optional,reference)"foo.less"; reference Use@import(reference)toimportexternalfiles,butwithoutaddingtheimportedstylestothecompiledoutputunlessreferenced. Releasedv1.5.0 Example:@import(reference)"foo.less"; Imaginethatreferencemarkseveryat-ruleandselectorwithareferenceflagintheimportedfile,importsasnormal,butwhentheCSSisgenerated,"reference"selectors(aswellasanymediaqueriescontainingonlyreferenceselectors)arenotoutput.referencestyleswillnotshowupinyourgeneratedCSSunlessthereferencestylesareusedasmixinsorextended. Additionally,referenceproducesdifferentresultsdependingonwhichmethodwasused(mixinorextend): extend:Whenaselectorisextended,onlythenewselectorismarkedasnotreferenced,anditispulledinatthepositionofthereference@importstatement. mixins:Whenareferencestyleisusedasanimplicitmixin,itsrulesaremixed-in,marked"notreference",andappearinthereferencedplaceasnormal. referenceexample Thisallowsyoutopullinonlyspecific,targetedstylesfromalibrarysuchasBootstrapbydoingsomethinglikethis: .navbar:extend(.navbarall){} Andyouwillpullinonly.navbarrelatedstylesfromBootstrap. inline Use@import(inline)toincludeexternalfiles,butnotprocessthem. Releasedv1.5.0 Example:@import(inline)"not-less-compatible.css"; YouwillusethiswhenaCSSfilemaynotbeLesscompatible;thisisbecausealthoughLesssupportsmostknownstandardsCSS,itdoesnotsupportcommentsinsomeplacesanddoesnotsupportallknownCSShackswithoutmodifyingtheCSS. SoyoucanusethistoincludethefileintheoutputsothatallCSSwillbeinonefile. less Use@import(less)totreatimportedfilesasLess,regardlessoffileextension. Releasedv1.4.0 Example: @import(less)"foo.css"; css Use@import(css)totreatimportedfilesasregularCSS,regardlessoffileextension.Thismeanstheimportstatementwillbeleftasitis. Releasedv1.4.0 Example: @import(css)"foo.less"; outputs @import"foo.less"; once Thedefaultbehaviorof@importstatements.Itmeansthefileisimportedonlyonceandsubsequentimportstatementsforthatfilewillbeignored. Releasedv1.4.0 Thisisthedefaultbehaviorof@importstatements. Example: @import(once)"foo.less"; @import(once)"foo.less";//thisstatementwillbeignored multiple Use@import(multiple)toallowimportingofmultiplefileswiththesamename.Thisistheoppositebehaviortoonce. Releasedv1.4.0 Example: //file:foo.less .a{ color:green; } //file:main.less @import(multiple)"foo.less"; @import(multiple)"foo.less"; Outputs .a{ color:green; } .a{ color:green; } optional Use@import(optional)toallowimportingofafileonlywhenitexists.WithouttheoptionalkeywordLessthrowsaFileErrorandstopscompilingwhenimportingafilethatcannotbefound. Releasedv2.3.0 @pluginAt-Rules Editthemarkdownsourcefor"plugins" Releasedv2.5.0 ImportJavaScriptpluginstoaddLess.jsfunctionsandfeatures Writingyourfirstplugin Usinga@[email protected]. @plugin"my-plugin";//automaticallyappends.jsifnoextension SinceLesspluginsareevaluatedwithintheLessscope,theplugindefinitioncanbequitesimple. registerPlugin({ install:function(less,pluginManager,functions){ functions.add('pi',function(){ returnMath.PI; }); } }) oryoucanusemodule.exports(shimmedtoworkinbrowseraswellasNode.js). module.exports={ install:function(less,pluginManager,functions){ functions.add('pi',function(){ returnMath.PI; }); } }; NotethatotherNode.jsCommonJSconventions,likerequire()arenotavailableinthebrowser.Keepthisinmindwhenwritingcross-platformplugins. Whatcanyoudowithaplugin?Alot,butlet'sstartwiththebasics.We'llfocusfirstonwhatyoumightputinsidetheinstallfunction.Let'ssayyouwritethis: //my-plugin.js install:function(less,pluginManager,functions){ functions.add('pi',function(){ returnMath.PI; }); } //etc Congratulations!You'vewrittenaLessplugin! Ifyouweretousethisinyourstylesheet: @plugin"my-plugin"; .show-me-pi{ value:pi(); } Youwouldget: .show-me-pi{ value:3.141592653589793; } However,youwouldneedtoreturnaproperLessnodeifyouwantedto,say,multiplythatagainstothervaluesordootherLessoperations.Otherwisetheoutputinyourstylesheetisplaintext(whichmaybefineforyourpurposes). Meaning,thisismorecorrect: functions.add('pi',function(){ returnnewtree.Dimension(Math.PI); }); Note:Adimensionisanumberwithorwithoutaunit,like"10px",whichwouldbeless.Dimension(10,"px").Foralistofunits,seetheLessAPI. Nowyoucanuseyourfunctioninoperations. @plugin"my-plugin"; .show-me-pi{ value:pi()*2; } Youmayhavenoticedthatthereareavailableglobalsforyourpluginfile,namelyafunctionregistry(functionsobject),andthelessobject.Thesearethereforconvenience. PluginScope Functionsaddedbya@pluginat-ruleadherestoLessscopingrules.ThisisgreatforLesslibraryauthorsthatwanttoaddfunctionalitywithoutintroducingnamingconflicts. Forinstance,sayyouhave2pluginsfromtwothird-partylibrariesthatbothhaveafunctionnamed"foo". //lib1.js //... functions.add('foo',function(){ return"foo"; }); //... //lib2.js //... functions.add('foo',function(){ return"bar"; }); //... That'sok!Youcanchoosewhichlibrary'sfunctioncreateswhichoutput. .el-1{ @plugin"lib1"; value:foo(); } .el-2{ @plugin"lib2"; value:foo(); } Thiswillproduce: .el-1{ value:foo; } .el-2{ value:bar; } Forpluginauthorssharingtheirplugins,thatmeansyoucanalsoeffectivelymakeprivatefunctionsbyplacingtheminaparticularscope.Asin,thiswillcauseanerror: .el{ @plugin"lib1"; } @value:foo(); AsofLess3.0,functionscanreturnanykindofNodetype,andcanbecalledatanylevel. Meaning,thiswouldthrowanerrorin2.x,asfunctionshadtobepartofthevalueofapropertyorvariableassignment: .block{ color:blue; my-function-rules(); } In3.x,that'snolongerthecase,andfunctionscanreturnAt-Rules,Rulesets,anyotherLessnode,strings,andnumbers(thelattertwoareconvertedtoAnonymousnodes). NullFunctions Therearetimeswhenyoumaywanttocallafunction,butyoudon'twantanythingoutput(suchasstoringavalueforlateruse).Inthatcase,youjustneedtoreturnfalsefromthefunction. varcollection=[]; functions.add('store',function(val){ collection.push(val);//immastorethisforlater returnfalse; }); @plugin"collections"; @var:32; store(@var); Lateryoucoulddosomethinglike: functions.add('retrieve',function(val){ returnnewtree.Value(collection); }); .get-my-values{ @plugin"collections"; values:retrieve(); } TheLess.jsPluginObject ALess.jspluginshouldexportanobjectthathasoneormoreoftheseproperties. { /*Calledimmediatelyafterthepluginis *firstimported,onlyonce.*/ install:function(less,pluginManager,functions){}, /*Calledforeachinstanceofyour@plugin.*/ use:function(context){}, /*Calledforeachinstanceofyour@plugin, *whenrulesarebeingevaluated. *It'sjustlaterintheevaluationlifecycle*/ eval:function(context){}, /*Passesanarbitrarystringtoyourplugin *e.g.@plugin(args)"file"; *Thisstringisnotparsedforyou, *soitcancontain(almost)anything*/ setOptions:function(argumentString){}, /*SetaminimumLesscompatibilitystring *Youcanalsouseanarray,asin[3,0]*/ minVersion:['3.0'], /*Usedforlessconly,toexplain *optionsinaTerminal*/ printUsage:function(){}, } ThePluginManagerinstancefortheinstall()functionprovidesmethodsforaddingvisitors,filemanagers,andpost-processors. Herearesomeexamplereposshowingthedifferentplugintypes. post-processor:https://github.com/less/less-plugin-clean-css visitor:https://github.com/less/less-plugin-inline-urls file-manager:https://github.com/less/less-plugin-npm-import Pre-LoadedPlugins Whilea@plugincallworkswellformostscenarios,therearetimeswhenyoumightwanttoloadapluginbeforeparsingstarts. See:Pre-LoadedPluginsinthe"UsingLess.js"sectionforhowtodothat. Maps(NEW!) Editthemarkdownsourcefor"maps" Releasedv3.5.0 Userulesetsandmixinsasmapsofvalues Bycombiningnamespacingwiththelookup[]syntax,youcanturnyourrulesets/mixinsintomaps. @sizes:{ mobile:320px; tablet:768px; desktop:1024px; } .navbar{ display:block; @media(min-width:@sizes[tablet]){ display:inline-block; } } Outputs: .navbar{ display:block; } @media(min-width:768px){ .navbar{ display:inline-block; } } Mixinsarealittlemoreversatileasmapsbecauseofnamespacingandtheabilitytooverloadmixins. #library(){ .colors(){ primary:green; secondary:blue; } } #library(){ .colors(){primary:grey;} } .button{ color:#library.colors[primary]; border-color:#library.colors[secondary]; } Outputs: .button{ color:grey; border-color:blue; } Youcanalsomakethiseasierbyaliasingmixins.Thatis: .button{ @colors:#library.colors(); color:@colors[primary]; border-color:@colors[secondary]; } Note,ifalookupvalueproducesanotherruleset,youcanappendasecond[]lookup,asin: @config:{ @options:{ library-on:true } } &when(@config[@options][library-on]=true){ .produce-ruleset{ prop:val; } } Inthisway,rulesetsandvariablecallscanemulateatypeof"namespacing",similartomixins. Asfaraswhethertousemixinsorrulesetsassignedtovariablesasmaps,it'suptoyou.Youmaywanttoreplaceentiremapsbyre-declaringavariableassignedtoarulset.Oryoumaywantto"merge"individualkey/valuepairs,inwhichcasemixinsasmapsmightbemoreappropriate. Usingvariablevariablesinlookups Oneimportantthingtonoticeisthatthevaluein[@lookup]isthekey(variable)name@lookup,andisnotevaluatedasavariable.Ifyouwantthekeynameitselftobevariable,youcanusethe@@variablesyntax. E.g. .foods(){ @dessert:icecream; } @key-to-lookup:dessert; .lunch{ treat:.foods[@@key-to-lookup]; } Thiswouldoutput: .lunch{ treat:icecream; }



請為這篇文章評分?