样式美化

0 阅读4分钟

样式和资产

遗憾的是,我们的 HotDog 应用程序还没有做好展示的准备--它完全没有风格!

在本章中,我们将为应用程序添加资产和样式。

Dioxus 使用 CSS 创建样式

如前所述,Dioxus 应用程序使用 HTML 和 CSS 作为核心标记和样式技术。我们在设计 Dioxus 时并没有像 Flutter 和 React-Native 那样重新发明轮子,而是在每个平台上都使用 HTML 和 CSS。

CSS 是目前最流行的样式系统,功能非常强大。例如,下面是 ebou 的截图,这是一款使用 Dioxus 构建的非常漂亮的 Mastodon 客户端。

HTML 和 CSS 功能强大,不必担心受到太多限制!

使用 * asset!()* 添加 CSS 文件

bare-bones 模板的 assets 文件夹中已经包含了一个基本的 main.css 文件。

├── Cargo.toml
├── assets
│   └── main.css
└── src
    └── main.rs

要在应用程序中包含 CSS,我们可以使用 asset!() 宏。该宏可确保资产包含在最终的应用程序捆绑包中。

static CSS: Asset = asset!("/assets/main.css");

我们还需要使用 document::Stylesheet 组件将资产加载到应用程序中。该组件等同于 <link> HTML 元素,但也能确保在服务器端渲染时预先加载 CSS。

fn App() -> Element {
    rsx! {
        document::Stylesheet { href: CSS }
    }
}

与 Rust 的 include_str!() 宏不同,asset!() 宏实际上不会将资产内容包含在最终可执行文件中。相反,它会生成一个唯一路径,以便在运行时加载资产。这非常适合通过不同 HTTP 请求并行加载资产的网络应用。

📣 asset!() 宏生成的唯一名称不会与输入名称完全匹配。这有助于防止名称碰撞并改进缓存。

热加载

Dioxus 中的所有资产都支持热加载。请尝试编辑您应用程序的 main.css,并观察实时改变的效果。

dog-asset-hotreload-9443436eb2d37278.gif

图片资源

在 Dioxus 中,您可以通过两种方式包含图片:

  • 动态使用 URL
  • 静态使用 asset!() 宏。 使用 URL 添加图片时,只需在 img {}src 属性中填入图片即可。请注意,当应用程序处于离线状态时,基于 URL 的图片将无法下载。
rsx! {
    // ...
    div {
        img { src: "https://images.dog.ceo/breeds/pitbull/dog-3981540_1280.jpg" }
    }
}

对于静态图片,您可以使用与包含应用程序 CSS 相同的 asset!()

static ICON: Asset = asset!("/assets/icon.png");

rsx! {
    img { src: ICON }
}

优化

默认情况下,asset!() 宏会对 CSS、JavaScript、JSON 和图片进行轻量级优化。资产名称也会被修改为_包含内容哈希值_。

// would output main-j1238nask123.css
asset!("/assets/main.css").to_string();

通过可选的选项结构,您还可以进一步优化资产。例如,dx 可以自动将 .png 图像转换为更优化的 .avif 格式:

// outputs icon-j1238jd2.avif
asset!("/assets/icon.png", ImageAssetOptions::new().with_avif());

对于许多应用程序来说,资产优化是改善加载时间的最有效方法。作为开发人员,我们经常会忽略图片的大小,一不小心就会导致网站加载速度变慢。

请查看资产指南,了解有关 Dioxus 资产系统工作原理的更深入解释。

最终 CSS

我们可以利用 dx 的资产热加载系统和 CSS 知识来创建一个漂亮的应用程序:

这里有最终的 CSS 供参考:

/* App-wide styling */
html, body {
    background-color: #0e0e0e;
    color: white;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    height: 100%;
    width: 100%;
    overflow: hidden;
    margin: 0;
}

#main {
    display: flex;
    flex-direction: column;
    height: 100%;
    justify-content: space-between;
}

#dogview {
    max-height: 80vh;
    flex-grow: 1;
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

#dogview img {
    display: block;
    max-width: 50%;
    max-height: 50%;
    transform: scale(1.8);
    border-radius: 5px;
    border: 1px solid rgb(233, 233, 233);
    box-shadow: 0px 0px 5px 1px rgb(216, 216, 216, 0.5);
}

#title {
    text-align: center;
    padding-top: 10px;
    border-bottom: 1px solid #a8a8a8;
    display: flex;
    flex-direction: row;
    justify-content: space-evenly;
    align-items: center;
}

#title a {
    text-decoration: none;
    color: white;
}

a#heart {
    background-color: white;
    color: red;
    padding: 5px;
    border-radius: 5px;
}

#title span {
    width: 20px;
}

#title h1 {
    margin: 0.25em;
    font-style: italic;
}

#buttons {
    display: flex;
    flex-direction: row;
    justify-content: center;
    gap: 20px;
    /* padding-top: 20px; */
    padding-bottom: 20px;
}

#skip { background-color: gray }
#save { background-color: green; }

#skip, #save {
    padding: 5px 30px 5px 30px;
    border-radius: 3px;
    font-size: 2rem;
    font-weight: bold;
    color: rgb(230, 230, 230)
}

#navbar {
    border: 1px solid rgb(233, 233, 233);
    border-width: 1px 0px 0px 0px;
    display: flex;
    flex-direction: row;
    justify-content: space-evenly;
    padding: 20px;
    gap: 20px;
}

#navbar a {
    background-color: #a8a8a8;
    border-radius: 5px;
    border: 1px solid black;
    text-decoration: none;
    color: black;
    padding: 10px 30px 10px 30px;
}

#favorites {
    flex-grow: 1;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    padding: 10px;
}

#favorites-container {
    overflow-y: auto;
    overflow-x: hidden;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px;
    padding: 10px;
}

.favorite-dog {
    max-height: 180px;
    max-width: 60%;
    position: relative;
}

.favorite-dog img {
    max-height: 150px;
    border-radius: 5px;
    margin: 5px;
}

.favorite-dog:hover button {
    display: block;
}

.favorite-dog button {
    display: none;
    position: absolute;
    bottom: 10px;
    left: 10px;
    z-index: 10;
}