Partilhar via


Aplicativos de estilo usando Folhas de Estilos em Cascata

Os aplicativos da interface do usuário de aplicativo multiplataforma do .NET (.NET MAUI) podem ser estilizados usando Folhas de Estilos em Cascata (CSS). Uma folha de estilos consiste de uma lista de regras, com cada regra consistindo de um ou mais seletores e um bloco de declaração. Um bloco de declaração consiste de uma lista de declarações entre chaves, com cada declaração consistindo de uma propriedade, dois pontos e um valor. Quando existem várias declarações em um bloco, um ponto e vírgula é inserido como separador.

O exemplo a seguir mostra algumas opções de CSS compatíveis com .NET MAUI:

navigationpage {
    -maui-bar-background-color: lightgray;
}

^contentpage {
    background-color: lightgray;
}

#listView {
    background-color: lightgray;
}

stacklayout {
    margin: 20;
    -maui-spacing: 6;
}

grid {
    row-gap: 6;
    column-gap: 6;
}
.mainPageTitle {
    font-style: bold;
    font-size: 14;
}

.mainPageSubtitle {
    margin-top: 15;
}

.detailPageTitle {
    font-style: bold;
    font-size: 14;
    text-align: center;
}

.detailPageSubtitle {
    text-align: center;
    font-style: italic;
}

listview image {
    height: 60;
    width: 60;
}

stacklayout>image {
    height: 200;
    width: 200;
}

No .NET MAUI, as folhas de estilo CSS são analisadas e avaliadas no runtime, não no momento da compilação, e as folhas de estilo são analisadas novamente quando em uso.

Importante

Não é possível estilizar um aplicativo do .NET MAUI totalmente usando CSS. No entanto, os estilos XAML podem ser usados para complementar o CSS. Para obter mais informações sobre estilos XAML, confira Criar o estilo de aplicativos usando XAML.

Consumir uma folha de estilos

O processo para adicionar uma folha de estilos a um aplicativo .NET MAUI é o seguinte:

  1. Adicione um arquivo CSS vazio ao seu projeto de aplicativo do .NET MAUI. O arquivo CSS pode ser colocado em qualquer pasta, com a pasta Recursos sendo o local recomendado.
  2. Defina a ação de compilar do arquivo CSS como MauiCss.

Como carregar uma folha de estilos

Existem várias abordagens que podem ser usadas para carregar uma folha de estilos.

Observação

Não é possível alterar uma folha de estilos no runtime e aplicar a nova folha de estilos.

Carregar uma folha de estilos em XAML

Uma folha de estilos pode ser carregada e analisada com a classe StyleSheet antes de ser adicionada a um ResourceDictionary:

<Application ...>
    <Application.Resources>
        <StyleSheet Source="/Resources/styles.css" />
    </Application.Resources>
</Application>

A propriedade StyleSheet.Source especifica a folha de estilos como um URI com relação ao local do arquivo XAML delimitado ou com relação à raiz do projeto, se o URI começar com um /.

Aviso

Você não conseguirá carregar o arquivo CSS se sua ação de compilar não estiver definida como MauiCss.

Alternativamente, uma folha de estilos pode ser carregada e analisada com a classe StyleSheet, antes de ser adicionada a um ResourceDictionary, ao ser incorporada a uma seção CDATA:

<ContentPage ...>
    <ContentPage.Resources>
        <StyleSheet>
            <![CDATA[
            ^contentpage {
                background-color: lightgray;
            }
            ]]>
        </StyleSheet>
    </ContentPage.Resources>
    ...
</ContentPage>

Para obter mais informações sobre dicionários de recursos, confira Dicionários de recursos.

Carregar uma folha de estilos em C#

No C#, uma folha de estilos pode ser carregada a partir de um StringReader e adicionada a um ResourceDictionary:

using Microsoft.Maui.Controls.StyleSheets;

public partial class MyPage : ContentPage
{
    public MyPage()
    {
        InitializeComponent();

        using (var reader = new StringReader("^contentpage { background-color: lightgray; }"))
        {
            this.Resources.Add(StyleSheet.FromReader(reader));
        }
    }
}

O argumento para o método StyleSheet.FromReader é o TextReader que leu a folha de estilos.

Selecionar elementos e aplicar propriedades

O CSS usa seletores para determinar quais elementos serão visados. Os estilos com seletores combinando são aplicados de forma consecutiva, na ordem da definição. Os estilos definidos em um item específico são sempre aplicados por último. Para obter mais informações sobre seletores com suporte, confira Referência de seletores.

O CSS usa propriedades para definir o estilo de um elemento selecionado. Cada propriedade tem um conjunto de valores possíveis e algumas propriedades podem afetar qualquer tipo de elemento, enquanto outras se aplicam a grupos de elementos. Para obter mais informações sobre propriedades com suporte, confira Referência de propriedades.

As folhas de estilo filhas sempre substituem as folhas de estilo pai se definirem as mesmas propriedades. Portanto, as seguintes regras de precedência são seguidas ao aplicar estilos que definem as mesmas propriedades:

  • Um estilo definido nos recursos do aplicativo será substituído por um estilo definido nos recursos da página, se definirem as mesmas propriedades.
  • Um estilo definido nos recursos da página será substituído por um estilo definido nos recursos de controle, se definirem as mesmas propriedades.
  • Um estilo definido nos recursos do aplicativo será substituído por um estilo definido nos recursos de controle, se definirem as mesmas propriedades.

Observação

As variáveis de CSS não têm suporte.

Selecionar elementos por tipo

Os elementos na árvore visual podem ser selecionados por tipo com o seletor de element, que não diferencia maiúsculas de minúsculas:

stacklayout {
    margin: 20;
}

Esse seletor identifica todos os elementos de StackLayout nas páginas que consomem a folha de estilos e define suas margens como uma espessura uniforme de 20.

Observação

O seletor de element não identifica subclasses do tipo especificado.

Como selecionar elementos por classe base

Os elementos na árvore visual podem ser selecionados pela classe base com o seletor de ^base, que não diferencia maiúsculas de minúsculas:

^contentpage {
    background-color: lightgray;
}

Esse seletor identifica todos os elementos de ContentPage que consomem a folha de estilos e define a cor da tela de fundo como lightgray.

Observação

O seletor ^base é específico do .NET MAUI e não faz parte da especificação do CSS.

Como selecionar um elemento por nome

Elementos individuais na árvore visual podem ser selecionados com o seletor de #id, que diferencia maiúsculas de minúsculas:

#listView {
    background-color: lightgray;
}

Esse seletor identifica o elemento cuja propriedade StyleId é definida como listView. No entanto, se a propriedade StyleId não estiver definida, o seletor irá retroceder e usar o x:Name do elemento. Portanto, no exemplo a seguir, o seletor #listView irá identificar o ListView cujo atributo x:Name está definido como listView e definir a cor da tela de fundo como lightgray.

<ContentPage ...>
    <ContentPage.Resources>
        <StyleSheet Source="/Resources/styles.css" />
    </ContentPage.Resources>
    <StackLayout>
        <ListView x:Name="listView">
            ...
        </ListView>
    </StackLayout>
</ContentPage>

Selecionar elementos com um atributo de classe específico

Elementos com um atributo de classe específico podem ser selecionados com o seletor de .class que diferencia maiúsculas de minúsculas:

.detailPageTitle {
    font-style: bold;
    font-size: 14;
    text-align: center;
}

.detailPageSubtitle {
    text-align: center;
    font-style: italic;
}

Uma classe de CSS pode ser atribuída a um elemento XAML ao definir a propriedade StyleClass do elemento como o nome da classe de CSS. Portanto, no exemplo a seguir, os estilos definidos pela classe .detailPageTitle são atribuídos ao primeiro Label, enquanto os estilos definidos pela classe .detailPageSubtitle são atribuídos ao segundo Label.

<ContentPage ...>
    <ContentPage.Resources>
        <StyleSheet Source="/Resources/styles.css" />
    </ContentPage.Resources>
    <ScrollView>
        <StackLayout>
            <Label ... StyleClass="detailPageTitle" />
            <Label ... StyleClass="detailPageSubtitle"/>
        </StackLayout>
    </ScrollView>
</ContentPage>

Selecionar elementos filhos

Os elementos filhos na árvore visual podem ser selecionados com o seletor de element element que não diferencia maiúsculas de minúsculas:

listview image {
    height: 60;
    width: 60;
}

Esse seletor identifica todos os elementos Image que são filhos de elementos ListView e define sua altura e largura como 60. Portanto, no exemplo de XAML a seguir, o seletor listview image irá identificar o Image, que é filho da ListView, e definir sua altura e largura como 60.

<ContentPage ...>
    <ContentPage.Resources>
        <StyleSheet Source="/Resources/styles.css" />
    </ContentPage.Resources>
    <StackLayout>
        <ListView ...>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid>
                            ...
                            <Image ... />
                            ...
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

Observação

O seletor element element não requer que o elemento filho seja um filho direto do pai: o elemento filho pode ter um pai diferente. A seleção ocorre sempre que um ancestral for o primeiro elemento especificado.

Selecionar elementos filhos diretos

Os elementos filhos diretos na árvore visual podem ser selecionados com o seletor element>element, que não diferencia maiúsculas de minúsculas:

stacklayout>image {
    height: 200;
    width: 200;
}

Esse seletor identifica todos os elementos Image que são filhos diretos de elementos StackLayout e define sua altura e largura como 200. Portanto, no exemplo a seguir, o seletor stacklayout>image irá identificar o Image que é um filho direto do StackLayout e definir sua altura e largura como 200.

<ContentPage ...>
    <ContentPage.Resources>
        <StyleSheet Source="/Resources/styles.css" />
    </ContentPage.Resources>
    <ScrollView>
        <StackLayout>
            ...
            <Image ... />
            ...
        </StackLayout>
    </ScrollView>
</ContentPage>

Observação

O seletor element>element requer que o elemento filho seja um filho direto do pai.

Referência de seletores

Os seguintes seletores de CSS são compatíveis com o .NET MAUI:

Seletor Exemplo Descrição
.class .header Seleciona todos os elementos com a propriedade StyleClass contendo "cabeçalho". Esse seletor diferencia maiúsculas de minúsculas.
#id #email Seleciona todos os elementos com StyleId definida como email. Se StyleId não estiver definida, retroceda para x:Name. Ao usar XAML, x:Name é preferível em vez de StyleId. Esse seletor diferencia maiúsculas de minúsculas.
* * Seleciona todos os elementos.
element label Seleciona todos os elementos do tipo Label, mas não subclasses. Esse seletor não diferencia maiúsculas de minúsculas.
^base ^contentpage Seleciona todos os elementos que têm ContentPage como classe base, incluindo a ContentPage propriamente dita. Esse seletor não diferencia maiúsculas de minúsculas e não faz parte da especificação do CSS.
element,element label,button Seleciona todos os elementos Button e todos os elementos Label. Esse seletor não diferencia maiúsculas de minúsculas.
element element stacklayout label Seleciona todos os elementos Label dentro de um StackLayout. Esse seletor não diferencia maiúsculas de minúsculas.
element>element stacklayout>label Seleciona todos os elementos Label que têm StackLayout como um pai direto. Esse seletor não diferencia maiúsculas de minúsculas.
element+element label+entry Seleciona todos os elementos Entry diretamente após um Label. Esse seletor não diferencia maiúsculas de minúsculas.
element~element label~entry Seleciona todos os elementos Entry precedidos por um Label. Esse seletor não diferencia maiúsculas de minúsculas.

Os estilos com seletores combinando são aplicados de forma consecutiva, na ordem da definição. Os estilos definidos em um item específico são sempre aplicados por último.

Dica

Os seletores podem ser combinados sem limitação, como em um StackLayout>ContentView>label.email.

Os seletores a seguir não têm suporte:

  • [attribute]
  • @media e @supports
  • : e ::

Observação

A especificidade e as substituições de especificidade não têm suporte.

Referência de propriedade

As seguintes propriedades de CSS são compatíveis com o .NET MAUI (na coluna Valores, os tipos são em itálico, enquanto os literais de cadeia de caracteres são gray):

Propriedade Aplicável ao Valores Exemplo
align-content FlexLayout stretch | center | start | end | spacebetween | spacearound | spaceevenly | flex-start | flex-end | space-between | space-around | initial align-content: space-between;
align-items FlexLayout stretch | center | start | end | flex-start | flex-end | initial align-items: flex-start;
align-self VisualElement auto | stretch | center | start | end | flex-start | flex-end | initial align-self: flex-end;
background-color VisualElement color | initial background-color: springgreen;
background-image Page cadeia de caracteres | initial background-image: bg.png;
border-color Button, Frame, ImageButton color | initial border-color: #9acd32;
border-radius BoxView, Button, Frame, ImageButton double | initial border-radius: 10;
border-width Button, ImageButton double | initial border-width: .5;
color ActivityIndicator, BoxView, Button, CheckBox, DatePicker, Editor, Entry, Label, Picker, ProgressBar, SearchBar, Switch, TimePicker color | initial color: rgba(255, 0, 0, 0.3);
column-gap Grid double | initial column-gap: 9;
direction VisualElement ltr | rtl | inherit | initial direction: rtl;
flex-direction FlexLayout column | columnreverse | row | rowreverse | row-reverse | column-reverse | initial flex-direction: column-reverse;
flex-basis VisualElement derivar | auto | initial. Além disso, um percentual no intervalo de 0% a 100% pode ser especificado com o sinal %. flex-basis: 25%;
flex-grow VisualElement float | initial flex-grow: 1.5;
flex-shrink VisualElement float | initial flex-shrink: 1;
flex-wrap VisualElement nowrap | wrap | reverse | wrap-reverse | initial flex-wrap: wrap-reverse;
font-family Button, DatePicker, Editor, Entry, Label, Picker, SearchBar, TimePicker, Span cadeia de caracteres | initial font-family: Consolas;
font-size Button, DatePicker, Editor, Entry, Label, Picker, SearchBar, TimePicker, Span double | initial font-size: 12;
font-style Button, DatePicker, Editor, Entry, Label, Picker, SearchBar, TimePicker, Span bold | italic | initial font-style: bold;
height VisualElement double | initial height: 250;
justify-content FlexLayout start | center | end | spacebetween | spacearound | spaceevenly | flex-start | flex-end | space-between | space-around | initial justify-content: flex-end;
letter-spacing Button, DatePicker, Editor, Entry, Label, Picker, SearchBar, SearchHandler, Span, TimePicker double | initial letter-spacing: 2.5;
line-height Label, Span double | initial line-height: 1.8;
margin View espessura | initial margin: 6 12;
margin-left View espessura | initial margin-left: 3;
margin-top View espessura | initial margin-top: 2;
margin-right View espessura | initial margin-right: 1;
margin-bottom View espessura | initial margin-bottom: 6;
max-lines Label int | initial max-lines: 2;
min-height VisualElement double | initial min-height: 50;
min-width VisualElement double | initial min-width: 112;
opacity VisualElement double | initial opacity: .3;
order VisualElement int | initial order: -1;
padding Button, ImageButton, Layout, Page espessura | initial padding: 6 12 12;
padding-left Button, ImageButton, Layout, Page double | initial padding-left: 3;
padding-top Button, ImageButton, Layout, Page double | initial padding-top: 4;
padding-right Button, ImageButton, Layout, Page double | initial padding-right: 2;
padding-bottom Button, ImageButton, Layout, Page double | initial padding-bottom: 6;
position FlexLayout relative | absolute | initial position: absolute;
row-gap Grid double | initial row-gap: 12;
text-align Entry, EntryCell, Label, SearchBar left | top | right | bottom | start | center | middle | end | initial. left e right deve ser evitados em ambientes com escrita da direita para a esquerda. text-align: right;
text-decoration Label, Span none | underline | strikethrough | line-through | initial text-decoration: underline, line-through;
text-transform Button,Editor, Entry, Label, SearchBar, SearchHandler none | default | uppercase | lowercase | initial text-transform: uppercase;
transform VisualElement none, rotate, rotateX, rotateY, scale, scaleX, scaleY, translate, translateX, translateY, initial transform: rotate(180), scaleX(2.5);
transform-origin VisualElement duplo, duplo | initial transform-origin: 7.5, 12.5;
vertical-align Label left | top | right | bottom | start | center | middle | end | initial vertical-align: bottom;
visibility VisualElement true | visible | false | hidden | collapse | initial visibility: hidden;
width VisualElement double | initial width: 320;

Observação

initial é um valor válido para todas as propriedades. Limpa o valor (redefine para o padrão) que foi definido em um outro estilo.

As seguintes propriedades não têm suporte:

  • all: initial.
  • Propriedades de layout (caixa ou grade).
  • Propriedades abreviadas, como font e border.

Além disso, não existe nenhum valor inherit e, portanto, a herança não tem suporte. Portanto, você não pode, por exemplo, definir a propriedade font-size em um layout e esperar que todas as instâncias de Label no layout herdem o valor. A única exceção é a propriedade direction, que tem um valor padrão inherit.

Importante

Os elementos Span não podem ser visados usando CSS.

Propriedades específicas do .NET MAUI

As seguintes propriedades de CSS específicas para o .NET MAUI também têm suporte (na coluna Valores, os tipos são em itálico, enquanto os literais de cadeia de caracteres são gray):

Propriedade Aplicável ao Valores Exemplo
-maui-bar-background-color NavigationPage, TabbedPage color | initial -maui-bar-background-color: teal;
-maui-bar-text-color NavigationPage, TabbedPage color | initial -maui-bar-text-color: gray
-maui-horizontal-scroll-bar-visibility ScrollView default | always | never | initial -maui-horizontal-scroll-bar-visibility: never;
-maui-max-length Entry, Editor, SearchBar int | initial -maui-max-length: 20;
-maui-max-track-color Slider color | initial -maui-max-track-color: red;
-maui-min-track-color Slider color | initial -maui-min-track-color: yellow;
-maui-orientation ScrollView, StackLayout horizontal | vertical | both | initial. both só tem suporte em uma ScrollView. -maui-orientation: horizontal;
-maui-placeholder Entry, Editor, SearchBar texto entre aspas | initial -maui-placeholder: Enter name;
-maui-placeholder-color Entry, Editor, SearchBar color | initial -maui-placeholder-color: green;
-maui-spacing StackLayout double | initial -maui-spacing: 8;
-maui-thumb-color Slider, Switch color | initial -maui-thumb-color: limegreen;
-maui-vertical-scroll-bar-visibility ScrollView default | always | never | initial -maui-vertical-scroll-bar-visibility: always;
-maui-vertical-text-alignment Label start | center | end | initial -maui-vertical-text-alignment: end;
-maui-visual VisualElement cadeia de caracteres | initial -maui-visual: material;

Propriedades específicas do Shell do .NET MAUI

As seguintes propriedades de CSS específicas para o Shell do .NET MAUI também têm suporte (na coluna Valores, os tipos são em itálico, enquanto os literais de cadeia de caracteres são gray):

Propriedade Aplicável ao Valores Exemplo
-maui-flyout-background Shell color | initial -maui-flyout-background: red;
-maui-shell-background Element color | initial -maui-shell-background: green;
-maui-shell-disabled Element color | initial -maui-shell-disabled: blue;
-maui-shell-foreground Element color | initial -maui-shell-foreground: yellow;
-maui-shell-tabbar-background Element color | initial -maui-shell-tabbar-background: white;
-maui-shell-tabbar-disabled Element color | initial -maui-shell-tabbar-disabled: black;
-maui-shell-tabbar-foreground Element color | initial -maui-shell-tabbar-foreground: gray;
-maui-shell-tabbar-title Element color | initial -maui-shell-tabbar-title: lightgray;
-maui-shell-tabbar-unselected Element color | initial -maui-shell-tabbar-unselected: cyan;
-maui-shell-title Element color | initial -maui-shell-title: teal;
-maui-shell-unselected Element color | initial -maui-shell-unselected: limegreen;

Color

Há suporte para os seguintes valores de color:

  • cores X11, que correspondem às cores do CSS e às cores do .NET MAUI. Esses valores de cor não diferenciam maiúsculas de minúsculas.
  • cores hexadecimais: #rgb, #argb, #rrggbb, #aarrggbb
  • cores rgb: rgb(255,0,0), rgb(100%,0%,0%). Os valores estão no intervalo de 0 a 255, ou 0%-100%.
  • cores rgba: rgba(255, 0, 0, 0.8), rgba(100%, 0%, 0%, 0.8). O valor de opacidade está no intervalo 0,0-1,0.
  • cores hsl: hsl(120, 100%, 50%). O valor h está no intervalo de 0-360, enquanto s e l estão no intervalo 0%-100%.
  • cores hsla: hsla(120, 100%, 50%, .8). O valor de opacidade está no intervalo 0,0-1,0.

Espessura

Os valores de thickness um, dois, três ou quatro têm suporte, cada um separado por um espaço em branco:

  • Um único valor indica uma espessura uniforme.
  • Dois valores indicam espessura vertical e, a seguir, horizontal.
  • Três valores indicam a espessura da parte superior, horizontal (esquerda e direita) e da parte inferior, nesta ordem.
  • Quatro valores indicam a espessura da parte superior, da direita, da parte inferior e da esquerda, nesta ordem.

Observação

Os valores de thickness de CSS diferem dos valores de Thickness de XAML. Por exemplo, em XAML, uma Thickness de dois valores indica a espessura horizontal, e a seguir vertical, enquanto uma Thickness de quatro valores indica a espessura da esquerda, da parte superior, da direita e da parte inferior, nesta ordem. Além disso, os valores de Thickness em XAML são delimitados por vírgula.

Funções

Gradientes lineares e radiais podem ser especificados usando as funções CSS linear-gradient() e radial-gradient(), respectivamente. O resultado dessas funções deve ser atribuído à propriedade background de um controle.