.NET 多平台应用 UI (.NET MAUI) 应用可以使用级联样式表(CSS)进行样式设置。 样式表由规则列表组成,每个规则由一个或多个选择器和声明块组成。 声明块由大括号中的声明列表组成,每个声明由属性、冒号和值组成。 当块中有多个声明时,分号将作为分隔符插入。
以下示例演示了一些符合 .NET MAUI 的 CSS:
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;
}
在 .NET MAUI 中,CSS 样式表在运行时进行分析和评估,而不是编译时,样式表将在使用时重新分析。
重要
无法使用 CSS 完全设置 .NET MAUI 应用的样式。 但是,XAML 样式可用于补充 CSS。 有关 XAML 样式的详细信息,请参阅 使用 XAML 样式应用。
使用样式表
将样式表添加到 .NET MAUI 应用的过程如下所示:
- 将空 CSS 文件添加到 .NET MAUI 应用项目。 CSS 文件可以放置在任何文件夹中,资源 文件夹是推荐的位置。
- 将 CSS 文件的生成操作设置为 MauiCss。
加载样式表
有多种方法可用于加载样式表。
注意
无法在运行时更改样式表并应用新的样式表。
在 XAML 中加载样式表
在将样式表添加到 ResourceDictionary之前,可以先使用 StyleSheet
类加载并解析它。
<Application ...>
<Application.Resources>
<StyleSheet Source="/Resources/styles.css" />
</Application.Resources>
</Application>
StyleSheet.Source
属性将样式表指定为相对于封闭 XAML 文件位置的 URI,或者如果 URI 以 /
开头,则指定为相对于项目根目录的 URI。
警告
如果 CSS 文件的生成操作未设置为 MauiCss,则将无法加载。
在将样式表内联到 ResourceDictionary并添加之前,可以通过使用 StyleSheet
类加载和解析样式表的方式,放入 CDATA
节中:
<ContentPage ...>
<ContentPage.Resources>
<StyleSheet>
<![CDATA[
^contentpage {
background-color: lightgray;
}
]]>
</StyleSheet>
</ContentPage.Resources>
...
</ContentPage>
有关资源字典的详细信息,请参阅 资源字典。
在 C 中加载样式表#
在 C# 中,可以从 StringReader
加载样式表并将其添加到 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));
}
}
}
StyleSheet.FromReader
方法的参数是已读取样式表的 TextReader
。
选择元素并应用属性
CSS 使用选择器来确定要定位的元素。 按定义顺序连续应用具有匹配选择器的样式。 对特定项定义的样式始终最后应用。 有关支持的选择器的详细信息,请参阅 选择器参考。
CSS 使用属性设置所选元素的样式。 每个属性都有一组可能的值,一些属性可能会影响任何类型的元素,而另一些属性则适用于元素组。 有关支持的属性的详细信息,请参阅 属性参考。
如果子样式表和父样式表设置了相同的属性,子样式表将始终优先于父样式表。 因此,应用设置相同属性的样式时,将遵循以下优先规则:
- 应用资源中定义的样式将被页面资源中定义的样式覆盖(如果它们设置了相同的属性)。
- 如果页面资源中定义的样式与控件资源中定义的样式设置了相同的属性,那么页面资源中的样式将会被覆盖。
- 如果控件资源中定义的样式与应用资源中定义的样式设置了相同的属性,应用资源中的样式将被覆盖。
注意
不支持 CSS 变量。
按类型选择元素
在可视化树中,可以使用不区分大小写的 element
选择器按类型选择元素。
stacklayout {
margin: 20;
}
此选择器标识使用样式表的页面上的任何 StackLayout 元素,并将页边距设置为 20 的统一粗细。
注意
element
选择器不标识指定类型的子类。
按基类选择元素
可视化树中的元素可以通过不区分大小写的 ^base
选择器来选择基类。
^contentpage {
background-color: lightgray;
}
此选择器标识使用样式表的任何 ContentPage 元素,并将其背景色设置为 lightgray
。
注意
^base
选择器特定于 .NET MAUI,不属于 CSS 规范。
按名称选择元素
可以使用区分大小写 #id
选择器选择可视化树中的单个元素:
#listView {
background-color: lightgray;
}
此选择器标识其 StyleId
属性设置为 listView
的元素。 但是,如果未设置 StyleId
属性,选择器将回退到使用元素 x:Name
。 因此,在以下示例中,#listView
选择器将标识其 x:Name
属性设置为 listView
的 ListView,并将其背景色设置为 lightgray
。
<ContentPage ...>
<ContentPage.Resources>
<StyleSheet Source="/Resources/styles.css" />
</ContentPage.Resources>
<StackLayout>
<ListView x:Name="listView">
...
</ListView>
</StackLayout>
</ContentPage>
选择具有特定类属性的元素
可以使用区分大小写 .class
选择器选择具有特定类属性的元素:
.detailPageTitle {
font-style: bold;
font-size: 14;
text-align: center;
}
.detailPageSubtitle {
text-align: center;
font-style: italic;
}
通过将元素的 StyleClass
属性设置为 CSS 类名称,可以将 CSS 类分配给 XAML 元素。 因此,在以下示例中,.detailPageTitle
类定义的样式将分配给第一个 Label,而 .detailPageSubtitle
类定义的样式则分配给第二个 Label。
<ContentPage ...>
<ContentPage.Resources>
<StyleSheet Source="/Resources/styles.css" />
</ContentPage.Resources>
<ScrollView>
<StackLayout>
<Label ... StyleClass="detailPageTitle" />
<Label ... StyleClass="detailPageSubtitle"/>
</StackLayout>
</ScrollView>
</ContentPage>
选择子元素
可以使用不区分大小写 element element
选择器选择可视化树中的子元素:
listview image {
height: 60;
width: 60;
}
此选择器标识 ListView 元素的任何 Image 子元素,并将其高度和宽度设置为 60 像素。 因此,在以下 XAML 示例中,listview image
选择器将标识 ListView的子级 Image,并将其高度和宽度设置为 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>
注意事项
element element
选择器不要求子元素是父级的 直接 子元素,子元素可能具有不同的父元素。 当祖先是指定的第一个元素时,将会发生选择。
选择直接子元素
可以通过不区分大小写 element>element
选择器选择可视化树中的直接子元素:
stacklayout>image {
height: 200;
width: 200;
}
此选择器标识 StackLayout 元素的直接子级的任何 Image 元素,并将其高度和宽度设置为 200。 因此,在下面的示例中,stacklayout>image
选择器将标识 StackLayout的直接子级 Image,并将其高度和宽度设置为 200。
<ContentPage ...>
<ContentPage.Resources>
<StyleSheet Source="/Resources/styles.css" />
</ContentPage.Resources>
<ScrollView>
<StackLayout>
...
<Image ... />
...
</StackLayout>
</ScrollView>
</ContentPage>
注意
element>element
选择器要求子元素是父级的直接 子元素。
选择器参考
.NET MAUI 支持以下 CSS 选择器:
选择器 | 例 | 描述 |
---|---|---|
.class |
.header |
选择包含“header”的 StyleClass 属性的所有元素。 此选择器区分大小写。 |
#id |
#email |
选择所有 StyleId 被设置为 email 的元素。 如果未设置 StyleId ,则回退到 x:Name 。 使用 XAML 时,首选 x:Name 而不是 StyleId 。 此选择器区分大小写。 |
* |
* |
选择所有元素。 |
element |
label |
选择类型为 Label的所有元素,但不包括这些元素的子类。 此选择器不区分大小写。 |
^base |
^contentpage |
选择 ContentPage 作为基类的所有元素,包括 ContentPage 本身。 此选择器不区分大小写,不属于 CSS 规范。 |
element,element |
label,button |
选择所有 Button 元素和所有 Label 元素。 此选择器不区分大小写。 |
element element |
stacklayout label |
选择 StackLayout中的所有 Label 元素。 此选择器不区分大小写。 |
element>element |
stacklayout>label |
选择所有直接父级为 StackLayout 的 Label 元素。 此选择器不区分大小写。 |
element+element |
label+entry |
直接在 Label之后选择所有 Entry 元素。 此选择器不区分大小写。 |
element~element |
label~entry |
选择前面有 Label的所有 Entry 元素。 此选择器不区分大小写。 |
按定义顺序连续应用具有匹配选择器的样式。 对特定项定义的样式始终最后应用。
提示
选择器可以组合在一起,且不受限制,例如 StackLayout>ContentView>label.email
。
不支持以下选择器:
[attribute]
-
@media
和@supports
-
:
和::
注意
不支持特定性和特定性替代。
如果两个或多个 CSS 规则指向同一元素,则具有最高特定性的选择器将优先,其样式声明将应用于该元素。 特异性算法 计算 CSS 选择器的权重,以确定多个竞争的 CSS 声明中哪个规则被应用于元素。
属性引用
.NET MAUI 支持以下 CSS 属性(在 值 列中,类型 斜体,而字符串文本 gray
):
财产 | 适用于 | 价值观 | 例 |
---|---|---|---|
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 |
颜色 | initial |
background-color: springgreen; |
background-image |
Page |
字符串 | initial |
background-image: bg.png; |
border-color |
Button、Frame、ImageButton |
颜色 | initial |
border-color: #9acd32; |
border-radius |
BoxView、Button、Frame、ImageButton |
双 | initial |
border-radius: 10; |
border-width |
Button,ImageButton |
双 | initial |
border-width: .5; |
color |
ActivityIndicator、BoxView、Button、CheckBox、DatePicker、Editor、Entry、Label、Picker、ProgressBar、SearchBar、Switch、TimePicker |
颜色 | initial |
color: rgba(255, 0, 0, 0.3); |
column-gap |
Grid |
双 | 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 |
浮点 | auto | initial 。 此外,可以使用 % 符号指定范围 0% 到 100% 中的百分比。 |
flex-basis: 25%; |
flex-grow |
VisualElement |
浮点 | initial |
flex-grow: 1.5; |
flex-shrink |
VisualElement |
浮点 | 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 |
字符串 | initial |
font-family: Consolas; |
font-size |
Button、DatePicker、Editor、Entry、Label、Picker、SearchBar、TimePicker、Span |
双 | initial |
font-size: 12; |
font-style |
Button、DatePicker、Editor、Entry、Label、Picker、SearchBar、TimePicker、Span | bold | italic | initial |
font-style: bold; |
height |
VisualElement |
双 | 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 |
双 | initial |
letter-spacing: 2.5; |
line-height |
Label,Span |
双 | initial |
line-height: 1.8; |
margin |
View |
厚度 | initial |
margin: 6 12; |
margin-left |
View |
厚度 | initial |
margin-left: 3; |
margin-top |
View |
厚度 | initial |
margin-top: 2; |
margin-right |
View |
厚度 | initial |
margin-right: 1; |
margin-bottom |
View |
厚度 | initial |
margin-bottom: 6; |
max-lines |
Label |
int | initial |
max-lines: 2; |
min-height |
VisualElement |
双 | initial |
min-height: 50; |
min-width |
VisualElement |
双 | initial |
min-width: 112; |
opacity |
VisualElement |
双 | initial |
opacity: .3; |
order |
VisualElement |
int | initial |
order: -1; |
padding |
Button、ImageButton、Layout、Page |
厚度 | initial |
padding: 6 12 12; |
padding-left |
Button、ImageButton、Layout、Page |
双 | initial |
padding-left: 3; |
padding-top |
Button、ImageButton、Layout、Page |
双 | initial |
padding-top: 4; |
padding-right |
Button、ImageButton、Layout、Page |
双 | initial |
padding-right: 2; |
padding-bottom |
Button、ImageButton、Layout、Page |
双 | initial |
padding-bottom: 6; |
position |
FlexLayout | relative | absolute | initial |
position: absolute; |
row-gap |
Grid |
双 | initial |
row-gap: 12; |
text-align |
Entry、EntryCell、Label、SearchBar |
left
|
top
|
right
|
bottom
|
start
|
center
|
middle
|
end
|
initial 。 应在从右到左的环境中避免 left 和 right 。 |
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 |
双,双 | 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 |
双 | initial |
width: 320; |
注意
initial
是所有属性的有效值。 它清除从另一种样式设置的值(重置为默认值)。
不支持以下属性:
-
all: initial
。 - 布局属性(框或网格)。
- 速记属性,如
font
和border
。
此外,没有 inherit
值,因此不支持继承。 因此,不能在布局上设置 font-size
属性,并期望布局中的所有 Label 实例继承该值。 一个例外是 direction
属性,该属性的默认值为 inherit
。
重要
Span 元素无法使用 CSS 进行定位。
.NET MAUI 特定属性
还支持以下特定于 .NET MAUI 的 CSS 属性(在 值 列中,类型 斜体,而字符串文本 gray
):
财产 | 适用于 | 价值观 | 例 |
---|---|---|---|
-maui-bar-background-color |
NavigationPage,TabbedPage |
颜色 | initial |
-maui-bar-background-color: teal; |
-maui-bar-text-color |
NavigationPage,TabbedPage |
颜色 | 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 |
颜色 | initial |
-maui-max-track-color: red; |
-maui-min-track-color |
Slider |
颜色 | initial |
-maui-min-track-color: yellow; |
-maui-orientation |
ScrollView,StackLayout |
horizontal
|
vertical
|
both
|
initial 。
both 仅在 ScrollView上受支持。 |
-maui-orientation: horizontal; |
-maui-placeholder |
Entry、Editor、SearchBar |
引用的文本 | initial |
-maui-placeholder: Enter name; |
-maui-placeholder-color |
Entry、Editor、SearchBar |
颜色 | initial |
-maui-placeholder-color: green; |
-maui-spacing |
StackLayout |
双 | initial |
-maui-spacing: 8; |
-maui-shadow |
VisualElement | 有效格式为:color、offsetX、offsetY | offsetX、offsetY、radius、color | offsetX、offsetY、radius、color、opacity | -maui-shadow: #000000 4 4; |
-maui-thumb-color |
Slider,Switch |
颜色 | 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 |
字符串 | initial |
-maui-visual: material; |
.NET MAUI Shell 特定属性
还支持以下特定于 .NET MAUI Shell 的 CSS 属性(在 值 列中,类型 斜体,而字符串文本 gray
):
财产 | 适用于 | 价值观 | 例 |
---|---|---|---|
-maui-flyout-background |
Shell |
颜色: | initial |
-maui-flyout-background: red; |
-maui-shell-background |
Element |
颜色 | initial |
-maui-shell-background: green; |
-maui-shell-disabled |
Element |
颜色 | initial |
-maui-shell-disabled: blue; |
-maui-shell-foreground |
Element |
颜色 | initial |
-maui-shell-foreground: yellow; |
-maui-shell-tabbar-background |
Element |
颜色 | initial |
-maui-shell-tabbar-background: white; |
-maui-shell-tabbar-disabled |
Element |
颜色 | initial |
-maui-shell-tabbar-disabled: black; |
-maui-shell-tabbar-foreground |
Element |
颜色 | initial |
-maui-shell-tabbar-foreground: gray; |
-maui-shell-tabbar-title |
Element |
颜色 | initial |
-maui-shell-tabbar-title: lightgray; |
-maui-shell-tabbar-unselected |
Element |
颜色 | initial |
-maui-shell-tabbar-unselected: cyan; |
-maui-shell-title |
Element |
颜色 | initial |
-maui-shell-title: teal; |
-maui-shell-unselected |
Element |
颜色 | initial |
-maui-shell-unselected: limegreen; |
颜色
支持以下 color
值:
-
X11
颜色,与 CSS 颜色和 .NET MAUI 颜色匹配。 这些颜色值不区分大小写。 - 十六进制颜色:
#rgb
、#argb
、#rrggbb
、#aarrggbb
- rgb 颜色:
rgb(255,0,0)
,rgb(100%,0%,0%)
。 值为 0-255 或 0%-100%。 - rgba 颜色:
rgba(255, 0, 0, 0.8)
、rgba(100%, 0%, 0%, 0.8)
。 不透明度值在 0.0-1.0 范围内。 - hsl 颜色:
hsl(120, 100%, 50%)
。 h 值在 0-360 范围内,s 和 l 位于范围 0%-100%。 - hsla 颜色:
hsla(120, 100%, 50%, .8)
。 不透明度值在 0.0-1.0 范围内。
厚度
支持一个、两个、三个或四个 thickness
值,每个值用空格分隔:
- 单个值表示均匀的粗细。
- 两个值指示垂直厚度和水平厚度。
- 三个值分别指示顶部、左右水平,然后是底部的厚度。
- 四个值分别表示上、右、下、左的厚度。
注意
CSS thickness
值不同于 XAML Thickness
值。 例如,在 XAML 中,双值 Thickness
表示水平和垂直厚度,而四值 Thickness
分别表示左、上、右、下厚度。 此外,XAML Thickness
值以逗号分隔。
功能
可以使用 linear-gradient()
和 radial-gradient()
CSS 函数分别指定线性和径向渐变。 这些函数的结果应分配给控件的 background
属性。