Partilhar via


Estilizar aplicativos usando folhas de estilo em cascata

Os aplicativos .NET Multi-platform App UI (.NET MAUI) podem ser estilizados usando folhas de estilo em cascata (CSS). Uma folha de estilos consiste em uma lista de regras, com cada regra consistindo de um ou mais seletores e um bloco de declaração. Um bloco de declarações consiste numa lista de declarações entre chavetas, com cada declaração consistindo de uma propriedade, dois pontos e um valor. Quando há várias declarações em um bloco, um ponto-e-vírgula é inserido como um separador.

O exemplo a seguir mostra alguns 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 em tempo de execução, em vez de tempo de compilação, e as folhas de estilo são reanalisadas no uso.

Importante

Não é possível estilizar totalmente um aplicativo .NET MAUI usando CSS. No entanto, os estilos XAML podem ser usados para complementar o CSS. Para obter mais informações sobre estilos XAML, consulte Estilizar aplicações 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 .NET MAUI. O arquivo CSS pode ser colocado em qualquer pasta, com a pasta Resources sendo o local recomendado.
  2. Defina a ação de compilação do arquivo CSS como MauiCss.

Carregando uma folha de estilos

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

Observação

Não é possível alterar uma folha de estilos em tempo de execução 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 relativo ao local do arquivo XAML que o inclui ou relativo à raiz do projeto se o URI começar com um /.

Advertência

O arquivo CSS falhará ao carregar se sua ação de compilação não estiver definida como MauiCss.

Como alternativa, uma folha de estilos pode ser carregada e analisada com a classe StyleSheet, antes de ser adicionada a um ResourceDictionary, inserindo-a em 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, consulte Dicionários de recursos.

Carregar uma folha de estilos em C#

Em C#, uma folha de estilos pode ser carregada 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 segmentar. Os estilos com seletores correspondentes são aplicados consecutivamente, em ordem de definição. Os estilos definidos em um item específico são sempre aplicados por último. Para obter mais informações sobre os seletores suportados, consulte a referência de seletores .

CSS usa propriedades para estilizar 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 suportadas, consulte Referência de propriedades.

As folhas de estilo filho 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 eles definirem as mesmas propriedades.
  • Um estilo definido em recursos de página será substituído por um estilo definido nos recursos de controle, se eles definirem as mesmas propriedades.
  • Um estilo definido nos recursos do aplicativo será substituído por um estilo definido nos recursos de controle, se eles definirem as mesmas propriedades.

Observação

As variáveis CSS não são suportadas.

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;
}

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

Observação

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

Seleção de elementos por classe base

Os elementos na árvore visual podem ser selecionados por classe base com o seletor ^base, que não distingue entre maiúsculas e minúsculas.

^contentpage {
    background-color: lightgray;
}

Este seletor identifica todos os elementos ContentPage que consomem a folha de estilos e define a cor do plano de fundo como lightgray.

Observação

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

Selecionando um elemento por nome

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

#listView {
    background-color: lightgray;
}

Este seletor identifica o elemento cuja propriedade StyleId está definida como listView. No entanto, se a propriedade StyleId não estiver definida, o seletor voltará a usar o x:Name do elemento. Portanto, no exemplo a seguir, o seletor de #listView identificará o ListView cujo atributo x:Name está definido como listViewe definirá sua cor de plano 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

Os elementos com um atributo de classe específico podem ser selecionados com o seletor de .class sensível a maiúsculas e minúsculas:

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

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

Uma classe CSS pode ser atribuída a um elemento XAML definindo a propriedade StyleClass do elemento como o nome da classe 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 filho

Os elementos filho 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;
}

Este seletor identifica todos os elementos Image que são filhos de ListView elementos e define sua altura e largura como 60. Portanto, no exemplo XAML a seguir, o seletor de listview image identificará o Image filho do ListViewe 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 de element element não exige que o elemento filho seja um direto filho do pai – o elemento filho pode ter um pai diferente. A seleção ocorre desde que um ancestral seja o primeiro elemento especificado.

Selecionar elementos filhos diretos

Os elementos filho diretos na árvore visual podem ser selecionados com o seletor de element>element sem diferenciação de maiúsculas e minúsculas:

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

Este seletor identifica todos os elementos Image que são filhos diretos de StackLayout elementos e define sua altura e largura para 200. Portanto, no exemplo a seguir, o seletor de stacklayout>image identificará o Image que é filho direto do StackLayoute 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 de element>element requer que o elemento filho seja um direto filho do pai.

Referência do seletor

Os seguintes seletores CSS são suportados pelo .NET MAUI:

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

Os estilos com seletores correspondentes são aplicados consecutivamente, em ordem de 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 StackLayout>ContentView>label.email.

Os seguintes seletores não são suportados:

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

Observação

Não há suporte para especificidade e sobreposição de especificidade.

Se duas ou mais regras CSS apontarem para o mesmo elemento, o seletor com a maior especificidade terá precedência e sua declaração de estilo será aplicada ao elemento. O algoritmo de especificidade calcula o peso de um seletor CSS para determinar qual regra de declarações CSS concorrentes é aplicada ao elemento.

Referência do imóvel

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

Propriedade Aplica-se a 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 cor | initial background-color: springgreen;
background-image Page string | initial background-image: bg.png;
border-color Button, Frame, ImageButton cor | initial border-color: #9acd32;
border-radius BoxView, Button, Frame, ImageButton duplo | initial border-radius: 10;
border-width Button, ImageButton duplo | initial border-width: .5;
color ActivityIndicator, BoxView, Button, CheckBox, DatePicker, Editor, Entry, Label, Picker, ProgressBar, SearchBar, Switch, TimePicker cor | initial color: rgba(255, 0, 0, 0.3);
column-gap Grid duplo | 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 flutuante | auto | initial. Além disso, uma porcentagem no intervalo de 0% a 100% pode ser especificada com o sinal de %. flex-basis: 25%;
flex-grow VisualElement flutuar | initial flex-grow: 1.5;
flex-shrink VisualElement flutuar | 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 string | initial font-family: Consolas;
font-size Button, DatePicker, Editor, Entry, Label, Picker, SearchBar, TimePicker, Span duplo | initial font-size: 12;
font-style Button, DatePicker, Editor, Entry, Label, Picker, SearchBar, TimePicker, Span bold | italic | initial font-style: bold;
height VisualElement duplo | 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 duplo | initial letter-spacing: 2.5;
line-height Label, Span duplo | 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 duplo | initial min-height: 50;
min-width VisualElement duplo | initial min-width: 112;
opacity VisualElement duplo | 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 duplo | initial padding-left: 3;
padding-top Button, ImageButton, Layout, Page duplo | initial padding-top: 4;
padding-right Button, ImageButton, Layout, Page duplo | initial padding-right: 2;
padding-bottom Button, ImageButton, Layout, Page duplo | initial padding-bottom: 6;
position FlexLayout relative | absolute | initial position: absolute;
row-gap Grid duplo | initial row-gap: 12;
text-align Entry, EntryCell, Label, SearchBar left | top | right | bottom | start | center | middle | end | initial. left e right devem ser evitados em ambientes 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 duplo | initial width: 320;

Observação

initial é um valor válido para todas as propriedades. Ele limpa o valor (redefine para padrão) que foi definido a partir de outro estilo.

As seguintes propriedades não são suportadas:

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

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

Importante

Span elementos não podem ser direcionados usando CSS.

Propriedades específicas do .NET MAUI

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

Propriedade Aplica-se a Valores Exemplo
-maui-bar-background-color NavigationPage, TabbedPage cor | initial -maui-bar-background-color: teal;
-maui-bar-text-color NavigationPage, TabbedPage cor | 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 cor | initial -maui-max-track-color: red;
-maui-min-track-color Slider cor | initial -maui-min-track-color: yellow;
-maui-orientation ScrollView, StackLayout horizontal | vertical | both | initial. both só é suportado em um ScrollView. -maui-orientation: horizontal;
-maui-placeholder Entry, Editor, SearchBar texto citado | initial -maui-placeholder: Enter name;
-maui-placeholder-color Entry, Editor, SearchBar cor | initial -maui-placeholder-color: green;
-maui-spacing StackLayout duplo | initial -maui-spacing: 8;
-maui-shadow VisualElement Os formatos válidos são: cor, deslocamentoX, deslocamentoY | deslocamentoX, deslocamentoY, raio, cor | deslocamentoX, deslocamentoY, raio, cor, opacidade -maui-shadow: #000000 4 4;
-maui-thumb-color Slider, Switch cor | 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 string | initial -maui-visual: material;

Propriedades específicas do .NET MAUI Shell

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

Propriedade Aplica-se a Valores Exemplo
-maui-flyout-background Shell cor | initial -maui-flyout-background: red;
-maui-shell-background Element cor | initial -maui-shell-background: green;
-maui-shell-disabled Element cor | initial -maui-shell-disabled: blue;
-maui-shell-foreground Element cor | initial -maui-shell-foreground: yellow;
-maui-shell-tabbar-background Element cor | initial -maui-shell-tabbar-background: white;
-maui-shell-tabbar-disabled Element cor | initial -maui-shell-tabbar-disabled: black;
-maui-shell-tabbar-foreground Element cor | initial -maui-shell-tabbar-foreground: gray;
-maui-shell-tabbar-title Element cor | initial -maui-shell-tabbar-title: lightgray;
-maui-shell-tabbar-unselected Element cor | initial -maui-shell-tabbar-unselected: cyan;
-maui-shell-title Element cor | initial -maui-shell-title: teal;
-maui-shell-unselected Element cor | initial -maui-shell-unselected: limegreen;

Cor

Os seguintes valores de color são suportados:

  • X11 cores, que correspondem às cores CSS e .NET MAUI. Esses valores de cor não são sensíveis a maiúsculas e minúsculas.
  • cores hexadecimais: #rgb, #argb, #rrggbb, #aarrggbb
  • Cores RGB: rgb(255,0,0), rgb(100%,0%,0%). Os valores estão no intervalo 0-255, ou 0%-100%.
  • rgba cores: 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 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

Há suporte para um, dois, três ou quatro valores thickness, cada um separado por espaço em branco:

  • Um único valor indica espessura uniforme.
  • Dois valores indicam espessura vertical e depois horizontal.
  • Três valores indicam a espessura superior, depois horizontal (esquerda e direita) e depois inferior.
  • Quatro valores indicam espessura superior, depois direita, depois inferior, depois esquerda.

Observação

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

Funções

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