Help language development. Donate to The Perl Foundation

CSS::Properties cpan:WARRINGD last updated on 2021-05-12

CSS-Properties-0.7.0/

[Raku CSS Project] / [CSS-Properties Module]

The CSS::Properties module is a set of related classes for parsing, manipulation and generation of CSS property sets, including inheritance, and defaults.

Synopsis

Classess in this module

See Also

Conformance Levels

Processing defaults to CSS level 3 (class CSS::Module::CSS3). This can be configured via the :module option:

use CSS::Properties;
use CSS::Module;
use CSS::Module::CSS1;
use CSS::Module::CSS21;
use CSS::Module::CSS3;

my $style = 'color: red; azimuth: left';

my CSS::Module $module = CSS::Module::CSS1.module;
my CSS::Properties $css1 .= new: :$style, :$module;
## warnings: dropping unknown property: azimuth

$module = CSS::Module::CSS21.module;
my CSS::Properties $css21 .= new: :$style, :$module;
## (no warnings)

my CSS::Properties $css3 .= new: :$style; # CSS3 is the default
# -- or --
$module = CSS::Module::CSS3.module;
$css3 .= new: :$style, :$module;

'@font-face' Properties

@font-face is a sub-module of CSS3. To process a set of @font-face declarations, such as:

@font-face {
    font-family: myFirstFont;
    src: url(sansation_light.woff);
}
use CSS::Properties;
use CSS::Module::CSS3;

my $style = "font-family: myFirstFont; src: url(sansation_light.woff)";
my $module = CSS::Module::CSS3.module.sub-module<@font-face>;
my CSS::Properties $font-face-css .= new( :$style, :$module);

Default values

Most properties have a default value. If a property is reset to its default value it will be omitted from stringification:

my $css = (require CSS::Properties).new;
say $css.background-image; # none
$css.background-image = 'url(camellia.png)';
say ~$css; # "background-image: url(camellia.png);"
$css.background-image = $css.info("background-image").default;
say ~$css; # ""

Deleting properties

Properties can be deleted via the delete method, or by assigning the property to Nil:

my CSS::Properties $css .= new: :style("background-position:top left; border-top-color:red; border-bottom-color: green; color: blue");
# delete background position
$css.background-position = Nil;
# delete all border colors
$css.delete: "border-color";

Inheritance

A child class can inherit from one or more parent classes. This follows CSS standards:

To inherit a css object or style string:

use CSS::Properties;

my $parent-style = "margin-top:5pt; margin-left: 15pt; color:rgb(0,0,255) !important";
my $style = "margin-top:25pt; margin-right: initial; margin-left: inherit; color:purple";
my CSS::Properties $css .= new: :$style, :inherit($parent-style);

say $css.color;                     # #7F007Frgb (purple)
say $css.handling("margin-left");   # inherit
say $css.margin-left;               # 15pt

Optimization and Serialization

method write(
    Bool :$optimize = True,        # consolidate properties
    Bool :$terse = True,           # single line output
    Bool :$color-names = True,     # use color names, where possible
    Bool :$keep-defaults = False,  # don't omit default values
    |c
) is also<Str gist> {

The .write (alias .Str, or .gist) method can be used to produce CSS. Properties are optimized and normalized:

use CSS::Properties;
my CSS::Properties $css .= new( :style("background-repeat:repeat; border-style: groove; border-width: 2pt 2pt; color: rgb(255,0,0);") );
# - 'border-width' and 'border-style' are consolidated to the 'border' container property
# - rgb(255,0,0) is mapped to 'red'
say $css.write;  # "border:2pt groove; color: red;"

Notice that:

$.write Options include:

ASTs can also be directly optimized:

use CSS::Properties;
use CSS::Module::CSS3;
use CSS::Writer;

my CSS::Properties $css .= new;
my $module = CSS::Module::CSS3.module;
my $actions = $module.actions.new;
my CSS::Writer $writer .= new: :color-names, :terse;
my $declarations = "border-bottom-color:red; border-bottom-style:solid; border-bottom-width:1px; border-left-color:red; border-left-style:solid; border-left-width:1px; border-right-color:red; border-right-style:solid; border-right-width:1px; border-top-color:red; border-top-style:solid; border-top-width:1px;";
my $p = $module.grammar.parse($declarations, :$actions, :rule<declaration-list>);
my %ast = $css.optimize($p.ast);
say $writer.write(|%ast); # border:1px solid red;

Property Meta-data

The info method gives property specific meta-data, on all (component or container properties). It returns an object of type CSS::Properties::Property:

use CSS::Properties;
my CSS::Properties $css .= new;
my $margin-info = $css.info("margin");
say $margin-info.synopsis; # <margin-width>{1,4}
say $margin-info.edges;    # [margin-top margin-right margin-bottom margin-left]
say $margin-info.inherit;  # True (property is inherited)

Data Introspection

The properties method, gives a list of current properties. Only component properties are returned. E.g. font-family may be returned; but font never is.

use CSS::Properties;

my $style = "margin-top: 10%; margin-right: 5mm; margin-bottom: auto";
my CSS::Properties $css .= new: :$style;

for $css.properties -> $prop {
    my $val = $css."$prop"();
    say "$prop: $val {$val.type}";
}

Gives:

margin-top: 10 percent
margin-bottom: auto keyw
margin-right: 5 mm

Length Units

CSS::Units is a convenience module that provides some simple post-fix length unit definitions.

The :ops export overloads + and - to perform unit calculations. +css and -css are also available as more explicit infix operators:

All infix operators convert to the left-hand operand's units.

use CSS::Units :ops, :pt, :px, :in, :mm;
my $css = (require CSS::Properties).new: :margin[5pt, 10px, .1in, 2mm];

# display margins in millimeters
say "%.2f mm".sprintf(.scale("mm")) for $css.margin.list;

Appendix : CSS3 Properties

Name Default Inherit Type Synopsis
azimuth center Yes \ \ [[ left-side \ far-left \ left \ center-left \ center \ center-right \ right \ far-right \ right-side ] \ \ behind ] \ leftwards \ rightwards
background hash ['background-color' \ \ 'background-image' \ \ 'background-repeat' \ \ 'background-attachment' \ \ 'background-position']
background-attachment scroll scroll \ fixed
background-color transparent \ \ transparent
background-image none \ \ none
background-position 0% 0% [ [ \ \ \ \ left \ center \ right ] [ \ \ \ \ top \ center \ bottom ]? ] \ [ [ left \ center \ right ] \ \ [ top \ center \ bottom ] ]
background-repeat repeat repeat \ repeat-x \ repeat-y \ no-repeat
border hash,box [ 'border-width' \ \ 'border-style' \ \ 'border-color' ]
border-bottom hash [ 'border-bottom-width' \ \ 'border-bottom-style' \ \ 'border-bottom-color' ]
border-bottom-color the value of the 'color' property \ \ transparent
border-bottom-style none \
border-bottom-width medium \
border-collapse separate Yes collapse \ separate
border-color box [ \ \ transparent ]{1,4}
border-left hash [ 'border-left-width' \ \ 'border-left-style' \ \ 'border-left-color' ]
border-left-color the value of the 'color' property \ \ transparent
border-left-style none \
border-left-width medium \
border-right hash [ 'border-right-width' \ \ 'border-right-style' \ \ 'border-right-color' ]
border-right-color the value of the 'color' property \ \ transparent
border-right-style none \
border-right-width medium \
border-spacing 0 Yes \ \?
border-style box \{1,4}
border-top hash [ 'border-top-width' \ \ 'border-top-style' \ \ 'border-top-color' ]
border-top-color the value of the 'color' property \ \ transparent
border-top-style none \
border-top-width medium \
border-width box \{1,4}
bottom auto \ \ \ \ auto
caption-side top Yes top \ bottom
clear none none \ left \ right \ both
clip auto \ \ auto
color depends on user agent Yes \
content normal normal \ none \ [ \ \ \ \ \ \ \ \ attr(\) \ open-quote \ close-quote \ no-open-quote \ no-close-quote ]+
counter-increment none none \ [ \ \? ]+
counter-reset none none \ [ \ \? ]+
cue hash [ 'cue-before' \ \ 'cue-after' ]
cue-after none \ \ none
cue-before none \ \ none
cursor auto Yes [ [\ ,]* [ auto \ crosshair \ default \ pointer \ move \ e-resize \ ne-resize \ nw-resize \ n-resize \ se-resize \ sw-resize \ s-resize \ w-resize \ text \ wait \ help \ progress ] ]
direction ltr Yes ltr \ rtl
display inline inline \ block \ list-item \ inline-block \ table \ inline-table \ table-row-group \ table-header-group \ table-footer-group \ table-row \ table-column-group \ table-column \ table-cell \ table-caption \ none
elevation level Yes \ \ below \ level \ above \ higher \ lower
empty-cells show Yes show \ hide
float none left \ right \ none
font Yes hash [ [ \<‘font-style’> \ \ \ \ \ \<‘font-weight’> \ \ \<‘font-stretch’> ]? \<‘font-size’> [ / \<‘line-height’> ]? \<‘font-family’> ] \ caption \ icon \ menu \ message-box \ small-caption \ status-bar
font-family depends on user agent Yes [ \ \ \ ]#
font-feature-settings normal Yes normal \ \#
font-kerning auto Yes auto \ normal \ none
font-language-override normal Yes normal \ \
font-size medium Yes \ \ \ \ \ \ \
font-size-adjust none Yes none \ auto \ \
font-stretch normal Yes normal \ ultra-condensed \ extra-condensed \ condensed \ semi-condensed \ semi-expanded \ expanded \ extra-expanded \ ultra-expanded
font-style normal Yes normal \ italic \ oblique
font-synthesis weight style Yes none \ [ weight \ \ style ]
font-variant normal Yes normal \ none \ [ \ \ \ \ \ \ \ \ \ \ \ \ stylistic(\) \ \ historical-forms \ \ styleset(\ #) \ \ character-variant(\ #) \ \ swash(\) \ \ ornaments(\) \ \ annotation(\) \ \ [ small-caps \ all-small-caps \ petite-caps \ all-petite-caps \ unicase \ titling-caps ] \ \ \ \ \ \ \ \ \ \ \ ordinal \ \ slashed-zero \ \ \ \ \ \ \ \ ruby ]
font-variant-alternates normal Yes normal \ [ stylistic(\) \ \ historical-forms \ \ styleset(\#) \ \ character-variant(\#) \ \ swash(\) \ \ ornaments(\) \ \ annotation(\) ]
font-variant-caps normal Yes normal \ small-caps \ all-small-caps \ petite-caps \ all-petite-caps \ unicase \ titling-caps
font-variant-east-asian normal Yes normal \ [ \ \ \ \ \ \ ruby ]
font-variant-ligatures normal Yes normal \ none \ [ \ \ \ \ \ \ \ \ \ \ ]
font-variant-numeric normal Yes normal \ [ \ \ \ \ \ \ \ \ \ ordinal \ \ slashed-zero ]
font-variant-position normal Yes normal \ sub \ super
font-weight normal Yes normal \ bold \ bolder \ lighter \ 100 \ 200 \ 300 \ 400 \ 500 \ 600 \ 700 \ 800 \ 900
height auto \ \ \ \ auto
left auto \ \ \ \ auto
letter-spacing normal Yes normal \ \
line-height normal Yes normal \ \ \ \ \ \
list-style Yes hash [ 'list-style-type' \ \ 'list-style-position' \ \ 'list-style-image' ]
list-style-image none Yes \ \ none
list-style-position outside Yes inside \ outside
list-style-type disc Yes disc \ circle \ square \ decimal \ decimal-leading-zero \ lower-roman \ upper-roman \ lower-greek \ lower-latin \ upper-latin \ armenian \ georgian \ lower-alpha \ upper-alpha \ none
margin box \{1,4}
margin-bottom 0 \
margin-left 0 \
margin-right 0 \
margin-top 0 \
max-height none \ \ \ \ none
max-width none \ \ \ \ none
min-height 0 \ \ \
min-width 0 \ \ \
opacity 1.0 \
orphans 2 Yes \
outline hash [ 'outline-color' \ \ 'outline-style' \ \ 'outline-width' ]
outline-color invert \ \ invert
outline-style none [ none \ hidden \ dotted \ dashed \ solid \ double \ groove \ ridge \ inset \ outset ]
outline-width medium thin \ medium \ thick \ \
overflow visible visible \ hidden \ scroll \ auto
padding box \{1,4}
padding-bottom 0 \
padding-left 0 \
padding-right 0 \
padding-top 0 \
page-break-after auto auto \ always \ avoid \ left \ right
page-break-before auto auto \ always \ avoid \ left \ right
page-break-inside auto avoid \ auto
pause [ [\ \ \]{1,2} ]
pause-after 0 \ \ \
pause-before 0 \ \ \
pitch medium Yes \ \ x-low \ low \ medium \ high \ x-high
pitch-range 50 Yes \
play-during auto \ [ mix \ \ repeat ]? \ auto \ none
position static static \ relative \ absolute \ fixed
quotes depends on user agent Yes [\ \]+ \ none
richness 50 Yes \
right auto \ \ \ \ auto
size auto \{1,2} \ auto \ [ \ \ \ [ portrait \ landscape] ]
speak normal Yes normal \ none \ spell-out
speak-header once Yes once \ always
speak-numeral continuous Yes digits \ continuous
speak-punctuation none Yes code \ none
speech-rate medium Yes \ \ x-slow \ slow \ medium \ fast \ x-fast \ faster \ slower
stress 50 Yes \
table-layout auto auto \ fixed
text-align a nameless value that acts as 'left' if 'direction' is 'ltr', 'right' if 'direction' is 'rtl' Yes left \ right \ center \ justify
text-decoration none none \ [ underline \ \ overline \ \ line-through \ \ blink ]
text-indent 0 Yes \ \ \
text-transform none Yes capitalize \ uppercase \ lowercase \ none
top auto \ \ \ \ auto
unicode-bidi normal normal \ embed \ bidi-override
vertical-align baseline baseline \ sub \ super \ top \ text-top \ middle \ bottom \ text-bottom \ \ \ \
visibility visible Yes visible \ hidden \ collapse
voice-family depends on user agent Yes [\ \ \ ]#
volume medium Yes \ \ \ \ silent \ x-soft \ soft \ medium \ loud \ x-loud
white-space normal Yes normal \ pre \ nowrap \ pre-wrap \ pre-line
widows 2 Yes \
width auto \ \ \ \ auto
word-spacing normal Yes normal \ \
z-index auto auto \ \

The above markdown table was produced with the following code snippet

use v6;
say <Name Default Inherit Type Synopsis>.join(' | ');
say ('---' xx 5).join(' | ');

my $css = (require CSS::Properties).new;

for $css.properties(:all).sort -> $name {
    with $css.info($name) {
        my @type;
        @type.push: 'hash' if .children;
        @type.push: 'box' if .box;
        my $synopsis-escaped = .synopsis.subst(/<?before <[ < | > # ]>>/, '\\', :g); 

        say ($name,
             .default // '',
             .inherit ?? 'Yes' !! '',
             @type.join(','),
             $synopsis-escaped,
            ).join(' | ');
    }
}