Aplicar estilo a las aplicaciones mediante hojas de estilos en cascada
Las aplicaciones de interfaz de usuario de aplicaciones multiplataforma de .NET (.NET MAUI) se pueden aplicar estilos mediante hojas de estilos en cascada (CSS). Una hoja de estilos consta de una lista de reglas, con cada regla que consta de uno o varios selectores y un bloque de declaración. Un bloque de declaración consta de una lista de declaraciones entre llaves, con cada declaración que consta de una propiedad, dos puntos y un valor. Cuando hay varias declaraciones en un bloque, se inserta un punto y coma como separador.
En el ejemplo siguiente se muestran algunos CSS compatibles con MAUI de .NET:
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;
}
En .NET MAUI, las hojas de estilos CSS se analizan y evalúan en tiempo de ejecución, en lugar de tiempo de compilación, y las hojas de estilos se vuelven a analizar en uso.
Importante
No es posible aplicar un estilo completo a una aplicación MAUI de .NET mediante CSS. Sin embargo, los estilos XAML se pueden usar para complementar CSS. Para obtener más información sobre los estilos XAML, consulta Aplicaciones de estilo con XAML.
Consumo de una hoja de estilos
El proceso para agregar una hoja de estilos a una aplicación MAUI de .NET es el siguiente:
- Agregue un archivo CSS vacío al proyecto de aplicación MAUI de .NET. El archivo CSS se puede colocar en cualquier carpeta, y la carpeta Resources es la ubicación recomendada.
- Establezca la acción de compilación del archivo CSS en MauiCss.
Cargar una hoja de estilos
Hay varios enfoques que se pueden usar para cargar una hoja de estilos.
Nota:
No es posible cambiar una hoja de estilos en tiempo de ejecución y aplicar la nueva hoja de estilos.
Cargar una hoja de estilos en XAML
Se puede cargar y analizar una hoja de estilos con la StyleSheet clase antes de agregarse a :ResourceDictionary
<Application ...>
<Application.Resources>
<StyleSheet Source="/Resources/styles.css" />
</Application.Resources>
</Application>
La StyleSheet.Source propiedad especifica la hoja de estilos como un URI relativo a la ubicación del archivo XAML envolvente, o en relación con la raíz del proyecto si el URI comienza por un /.
Advertencia
El archivo CSS no se cargará si su acción de compilación no está establecida en MauiCss.
Como alternativa, se puede cargar y analizar una hoja de estilos con la StyleSheet clase , antes de agregarla a un ResourceDictionaryelemento , insertándola en una CDATA sección:
<ContentPage ...>
<ContentPage.Resources>
<StyleSheet>
<![CDATA[
^contentpage {
background-color: lightgray;
}
]]>
</StyleSheet>
</ContentPage.Resources>
...
</ContentPage>
Para obtener más información sobre los diccionarios de recursos, consulte Diccionarios de recursos.
Cargar una hoja de estilos en C #
En C#, se puede cargar una hoja de estilos desde y StringReader agregarla a :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));
}
}
}
El argumento del StyleSheet.FromReader método es el TextReader que ha leído la hoja de estilos.
Seleccionar elementos y aplicar propiedades
CSS usa selectores para determinar qué elementos se van a establecer como destino. Los estilos con selectores coincidentes se aplican de forma consecutiva, en orden de definición. Los estilos definidos en un elemento específico siempre se aplican en último lugar. Para obtener más información sobre los selectores admitidos, vea Referencia del selector.
CSS usa propiedades para aplicar estilo a un elemento seleccionado. Cada propiedad tiene un conjunto de valores posibles y algunas propiedades pueden afectar a cualquier tipo de elemento, mientras que otras se aplican a grupos de elementos. Para obtener más información sobre las propiedades admitidas, vea Referencia de propiedades.
Las hojas de estilos secundarias siempre invalidan las hojas de estilos primarias si establecen las mismas propiedades. Por lo tanto, se siguen las siguientes reglas de precedencia al aplicar estilos que establecen las mismas propiedades:
- Un estilo definido en los recursos de la aplicación se sobrescribirá mediante un estilo definido en los recursos de página, si establecen las mismas propiedades.
- Un estilo definido en los recursos de página se sobrescribirá mediante un estilo definido en los recursos de control, si establecen las mismas propiedades.
- Un estilo definido en los recursos de la aplicación se sobrescribirá mediante un estilo definido en los recursos de control, si establecen las mismas propiedades.
Nota:
Las variables CSS no son compatibles.
Seleccionar elementos por tipo
Los elementos del árbol visual se pueden seleccionar por tipo con el selector sin distinción entre mayúsculas y minúsculas element :
stacklayout {
margin: 20;
}
Este selector identifica los StackLayout elementos de las páginas que consumen la hoja de estilos y establece sus márgenes en un grosor uniforme de 20.
Nota:
El element selector no identifica subclases del tipo especificado.
Selección de elementos por clase base
Los elementos del árbol visual se pueden seleccionar mediante la clase base con el selector sin distinción entre mayúsculas y minúsculas ^base :
^contentpage {
background-color: lightgray;
}
Este selector identifica los ContentPage elementos que consumen la hoja de estilos y establece su color de fondo en lightgray.
Nota:
El ^base selector es específico de .NET MAUI y no forma parte de la especificación CSS.
Selección de un elemento por nombre
Los elementos individuales del árbol visual se pueden seleccionar con el selector de distinción entre mayúsculas y minúsculas #id :
#listView {
background-color: lightgray;
}
Este selector identifica el elemento cuya StyleId propiedad se establece listViewen . Sin embargo, si la StyleId propiedad no está establecida, el selector volverá a usar el x:Name del elemento . Por lo tanto, en el ejemplo siguiente, el #listView selector identificará el ListView atributo cuyo x:Name atributo está establecido listViewen y establecerá el color de fondo en lightgray.
<ContentPage ...>
<ContentPage.Resources>
<StyleSheet Source="/Resources/styles.css" />
</ContentPage.Resources>
<StackLayout>
<ListView x:Name="listView">
...
</ListView>
</StackLayout>
</ContentPage>
Seleccionar elementos con un atributo de clase específico
Los elementos con un atributo de clase específico se pueden seleccionar con el selector que distingue mayúsculas de minúsculas .class :
.detailPageTitle {
font-style: bold;
font-size: 14;
text-align: center;
}
.detailPageSubtitle {
text-align: center;
font-style: italic;
}
Una clase CSS se puede asignar a un elemento XAML estableciendo la StyleClass propiedad del elemento en el nombre de clase CSS. Por lo tanto, en el ejemplo siguiente, los estilos definidos por la .detailPageTitle clase se asignan al primer Label, mientras que los estilos definidos por la .detailPageSubtitle clase se asignan al segundo Label.
<ContentPage ...>
<ContentPage.Resources>
<StyleSheet Source="/Resources/styles.css" />
</ContentPage.Resources>
<ScrollView>
<StackLayout>
<Label ... StyleClass="detailPageTitle" />
<Label ... StyleClass="detailPageSubtitle"/>
</StackLayout>
</ScrollView>
</ContentPage>
Seleccionar elementos secundarios
Los elementos secundarios del árbol visual se pueden seleccionar con el selector sin distinción entre mayúsculas y element element minúsculas:
listview image {
height: 60;
width: 60;
}
Este selector identifica los Image elementos secundarios de ListView los elementos y establece su alto y ancho en 60. Por lo tanto, en el ejemplo XAML siguiente, el listview image selector identificará que Image es un elemento secundario de ListViewy establece su alto y ancho en 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>
Nota:
El element element selector no requiere que el elemento secundario sea un elemento secundario directo del elemento primario: el elemento secundario puede tener un elemento primario diferente. La selección se produce siempre que un antecesor sea el primer elemento especificado.
Selección de elementos secundarios directos
Los elementos secundarios directos del árbol visual se pueden seleccionar con el selector sin distinción entre mayúsculas y minúsculas element>element :
stacklayout>image {
height: 200;
width: 200;
}
Este selector identifica los Image elementos que son elementos secundarios directos de StackLayout los elementos y establece su alto y ancho en 200. Por lo tanto, en el ejemplo siguiente, el stacklayout>image selector identificará que Image es un elemento secundario directo de StackLayouty establece su alto y ancho en 200.
<ContentPage ...>
<ContentPage.Resources>
<StyleSheet Source="/Resources/styles.css" />
</ContentPage.Resources>
<ScrollView>
<StackLayout>
...
<Image ... />
...
</StackLayout>
</ScrollView>
</ContentPage>
Nota:
El element>element selector requiere que el elemento secundario sea un elemento secundario directo del elemento primario.
Referencia del selector
Los siguientes selectores CSS son compatibles con .NET MAUI:
| Selector | Ejemplo | Descripción |
|---|---|---|
.class |
.header |
Selecciona todos los elementos con la StyleClass propiedad que contiene "header". Este selector distingue mayúsculas de minúsculas. |
#id |
#email |
Selecciona todos los elementos con StyleId establecido en email. Si StyleId no se establece, reserva en x:Name. Al usar XAML, x:Name se prefiere a StyleId. Este selector distingue mayúsculas de minúsculas. |
* |
* |
Selecciona todos los elementos. |
element |
label |
Selecciona todos los elementos de tipo Label, pero no subclases. Este selector no distingue mayúsculas de minúsculas. |
^base |
^contentpage |
Selecciona todos los elementos con ContentPage como clase base, incluido ContentPage a sí mismo. Este selector no distingue mayúsculas de minúsculas y no forma parte de la especificación CSS. |
element,element |
label,button |
Selecciona todos los Button elementos y todos los Label elementos. Este selector no distingue mayúsculas de minúsculas. |
element element |
stacklayout label |
Selecciona todos los Label elementos dentro de .StackLayout Este selector no distingue mayúsculas de minúsculas. |
element>element |
stacklayout>label |
Selecciona todos los Label elementos con StackLayout como elemento primario directo. Este selector no distingue mayúsculas de minúsculas. |
element+element |
label+entry |
Selecciona todos los Entry elementos directamente después de .Label Este selector no distingue mayúsculas de minúsculas. |
element~element |
label~entry |
Selecciona todos los Entry elementos precedidos de .Label Este selector no distingue mayúsculas de minúsculas. |
Los estilos con selectores coincidentes se aplican consecutivamente, en orden de definición. Los estilos definidos en un elemento específico siempre se aplican en último lugar.
Sugerencia
Los selectores se pueden combinar sin limitación, como StackLayout>ContentView>label.email.
No se admiten los siguientes selectores:
[attribute]@mediay@supports:y::
Nota:
La especificidad y las invalidaciones de especificidad no son compatibles.
Referencia de propiedades
.NET MAUI admite las siguientes propiedades CSS (en la columna Valores , los tipos son cursiva, mientras que los literales de cadena son gray):
| Propiedad | Se aplica a | Valores | Ejemplo |
|---|---|---|---|
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 |
Cadena | initial |
background-image: bg.png; |
border-color |
Button, Frame, ImageButton |
Color | initial |
border-color: #9acd32; |
border-radius |
BoxView, Button, Frame, ImageButton |
Doble | initial |
border-radius: 10; |
border-width |
Button, ImageButton |
Doble | 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 |
Doble | 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 |
float | auto | initial. Además, se puede especificar un porcentaje del intervalo del 0 % al 100 % con el % signo . |
flex-basis: 25%; |
flex-grow |
VisualElement |
Flotador | initial |
flex-grow: 1.5; |
flex-shrink |
VisualElement |
Flotador | 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 |
Cadena | initial |
font-family: Consolas; |
font-size |
Button, DatePicker, Editor, Entry, Label, Picker, SearchBar, TimePicker, Span |
Doble | initial |
font-size: 12; |
font-style |
Button, DatePicker, Editor, Entry, Label, Picker, SearchBar, TimePicker, Span |
bold | italic | initial |
font-style: bold; |
height |
VisualElement |
Doble | initial |
min-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 |
Doble | initial |
letter-spacing: 2.5; |
line-height |
Label, Span |
Doble | initial |
line-height: 1.8; |
margin |
View |
Grueso | initial |
margin: 6 12; |
margin-left |
View |
Grueso | initial |
margin-left: 3; |
margin-top |
View |
Grueso | initial |
margin-top: 2; |
margin-right |
View |
Grueso | initial |
margin-right: 1; |
margin-bottom |
View |
Grueso | initial |
margin-bottom: 6; |
max-lines |
Label |
Int | initial |
max-lines: 2; |
min-height |
VisualElement |
Doble | initial |
min-height: 50; |
min-width |
VisualElement |
Doble | initial |
min-width: 112; |
opacity |
VisualElement |
Doble | initial |
opacity: .3; |
order |
VisualElement |
Int | initial |
order: -1; |
padding |
Button, ImageButton, Layout, Page |
Grueso | initial |
padding: 6 12 12; |
padding-left |
Button, ImageButton, Layout, Page |
Doble | initial |
padding-left: 3; |
padding-top |
Button, ImageButton, Layout, Page |
Doble | initial |
padding-top: 4; |
padding-right |
Button, ImageButton, Layout, Page |
Doble | initial |
padding-right: 2; |
padding-bottom |
Button, ImageButton, Layout, Page |
Doble | initial |
padding-bottom: 6; |
position |
FlexLayout |
relative | absolute | initial |
position: absolute; |
row-gap |
Grid |
Doble | initial |
row-gap: 12; |
text-align |
Entry, EntryCell, Label, SearchBar |
left | top | right | bottom | start | center | middle | end | initial. left y right deben evitarse en entornos de derecha a izquierda. |
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 |
double, double | 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 |
Doble | initial |
min-width: 320; |
Nota:
initial es un valor válido para todas las propiedades. Borra el valor (se restablece de forma predeterminada) que se estableció a partir de otro estilo.
No se admiten las siguientes propiedades:
all: initial.- Propiedades de diseño (cuadro o cuadrícula).
- Propiedades abreviadas, como
font, yborder.
Además, no hay ningún inherit valor y, por tanto, no se admite la herencia. Por lo tanto, no puede, por ejemplo, establecer la font-size propiedad en un diseño y esperar que todas las Label instancias del diseño hereden el valor. La única excepción es la direction propiedad , que tiene un valor predeterminado de inherit.
Importante
Span los elementos no se pueden establecer como destino mediante CSS.
Propiedades específicas de .NET MAUI
También se admiten las siguientes propiedades CSS específicas de .NET MAUI (en la columna Valores , los tipos son cursiva, mientras que los literales de cadena son gray):
| Propiedad | Se aplica a | Valores | Ejemplo |
|---|---|---|---|
-maui-bar-background-color |
NavigationPage, TabbedPage |
Color | initial |
-xf-bar-background-color: teal; |
-maui-bar-text-color |
NavigationPage, TabbedPage |
Color | initial |
-xf-bar-text-color: gray |
-maui-horizontal-scroll-bar-visibility |
ScrollView |
default | always | never | initial |
-xf-horizontal-scroll-bar-visibility: never; |
-maui-max-length |
Entry, Editor, SearchBar |
Int | initial |
-xf-max-length: 20; |
-maui-max-track-color |
Slider |
Color | initial |
-xf-max-track-color: red; |
-maui-min-track-color |
Slider |
Color | initial |
-xf-min-track-color: yellow; |
-maui-orientation |
ScrollView, StackLayout |
horizontal | vertical | both | initial. bothsolo se admite en .ScrollView |
-xf-orientation: horizontal; |
-maui-placeholder |
Entry, Editor, SearchBar |
texto entre comillas | initial |
-xf-placeholder: Enter name; |
-maui-placeholder-color |
Entry, Editor, SearchBar |
Color | initial |
-xf-placeholder-color: green; |
-maui-spacing |
StackLayout |
Doble | initial |
-xf-spacing: 8; |
-maui-thumb-color |
Slider, Switch |
Color | initial |
-xf-thumb-color: limegreen; |
-maui-vertical-scroll-bar-visibility |
ScrollView |
default | always | never | initial |
-xf-vertical-scroll-bar-visibility: always; |
-maui-vertical-text-alignment |
Label |
start | center | end | initial |
-xf-vertical-text-alignment: end; |
-maui-visual |
VisualElement |
Cadena | initial |
-xf-visual: material; |
Propiedades específicas del shell de .NET MAUI
También se admiten las siguientes propiedades CSS específicas del shell maui de .NET (en la columna Valores , los tipos son cursiva, mientras que los literales de cadena son gray):
| Propiedad | Se aplica a | Valores | Ejemplo |
|---|---|---|---|
-maui-flyout-background |
Shell |
Color | initial |
-xf-flyout-background: red; |
-maui-shell-background |
Element |
Color | initial |
-xf-shell-background: green; |
-maui-shell-disabled |
Element |
Color | initial |
-xf-shell-disabled: blue; |
-maui-shell-foreground |
Element |
Color | initial |
-xf-shell-foreground: yellow; |
-maui-shell-tabbar-background |
Element |
Color | initial |
-xf-shell-tabbar-background: white; |
-maui-shell-tabbar-disabled |
Element |
Color | initial |
-xf-shell-tabbar-disabled: black; |
-maui-shell-tabbar-foreground |
Element |
Color | initial |
-xf-shell-tabbar-foreground: gray; |
-maui-shell-tabbar-title |
Element |
Color | initial |
-xf-shell-tabbar-title: lightgray; |
-maui-shell-tabbar-unselected |
Element |
Color | initial |
-xf-shell-tabbar-unselected: cyan; |
-maui-shell-title |
Element |
Color | initial |
-xf-shell-title: teal; |
-maui-shell-unselected |
Element |
Color | initial |
-xf-shell-unselected: limegreen; |
Color
Se admiten los siguientes color valores:
X11colores, que coinciden con los colores CSS y los colores maui de .NET. Estos valores de color no distinguen mayúsculas de minúsculas.- colores hexadecimales:
#rgb,#argb,#rrggbb,#aarrggbb - colores rgb:
rgb(255,0,0),rgb(100%,0%,0%). Los valores están comprendidos entre 0 y 255 o 0%-100%. - colores rgba:
rgba(255, 0, 0, 0.8),rgba(100%, 0%, 0%, 0.8). El valor de opacidad está en el intervalo 0,0-1,0. - Colores hsl:
hsl(120, 100%, 50%). El valor h está en el intervalo 0-360, mientras que s y l están en el intervalo 0%-100%. - hsla colors:
hsla(120, 100%, 50%, .8). El valor de opacidad está en el intervalo 0,0-1,0.
Thickness
Se admiten uno, dos, tres o cuatro thickness valores, cada uno separado por espacios en blanco:
- Un valor único indica un grosor uniforme.
- Dos valores indican el grosor vertical y horizontal.
- Tres valores indican superior y horizontal (izquierda y derecha), después grosor inferior.
- Cuatro valores indican la parte superior, la derecha, la parte inferior y el grosor izquierdo.
Nota:
Los valores CSS thickness difieren de los valores XAML Thickness . Por ejemplo, en XAML, un valor de dos valores Thickness indica el grosor horizontal y vertical, mientras que un valor Thickness de cuatro valores indica a la izquierda, a continuación, arriba, derecha y después grosor inferior. Además, los valores XAML Thickness están delimitados por comas.
Functions
Los degradados lineales y radiales se pueden especificar mediante las linear-gradient() funciones CSS y radial-gradient() , respectivamente. El resultado de estas funciones debe asignarse a la background propiedad de un control .