layout
概述
layout 标签用于设置模板使用的布局文件,或者禁用布局渲染。布局文件提供了页面的整体结构(如 HTML 骨架、导航栏、页脚等),模板内容会被插入到布局的指定位置。语法
{% layout "布局名称" %} <!-- 使用指定布局 -->
{% layout none %} <!-- 不使用布局 -->
布局文件位置
布局文件位于主题的
layout/ 目录下,例如: - layout/theme.liquid - 默认主题布局 - layout/custom.liquid - 自定义布局 - layout/mobile.liquid - 移动端布局使用示例
1. 使用默认布局
如果不设置
layout 标签,模板会默认使用 layout/theme.liquid 布局。<h1>页面标题</h1>
<p>页面内容</p>
模板内容会被插入到布局文件的
{{ content_for_layout }} 位置。2. 使用自定义布局
指定使用特定的布局文件。
{% layout "custom" %}
<h1>页面标题</h1>
<p>页面内容</p>
这会使用
layout/custom.liquid 作为布局文件。3. 禁用布局
当需要返回完整的 HTML 页面或非 HTML 格式的响应时,禁用布局。
{% layout none %}
<html>
<head>
<title>独立页面</title>
</head>
<body>
<h1>完整 HTML 页面</h1>
</body>
</html>
4. 条件设置布局
根据条件动态选择不同的布局。
{% if params.mobile == "true" %}
{% layout "mobile" %}
{% else %}
{% layout "desktop" %}
{% endif %}
<h1>页面标题</h1>
<p>页面内容</p>
5. 配合 response_type 使用
当使用非 HTML 响应类型时,必须禁用布局。
{% response_type "json" %}
{% layout none %}
{
"status": "success",
"data": {}
}
{% response_type "turbo_stream" %}
{% layout none %}
<turbo-stream action="replace" target="content">
<template>
<div id="content">更新后的内容</div>
</template>
</turbo-stream>
布局文件结构
布局文件通常包含页面的基本结构,模板内容会被插入到
content_for_layout 变量位置。示例:
layout/theme.liquid<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{{ page.title }}</title>
{% meta_tags %}
</head>
<body>
<header>
<!-- 导航栏 -->
</header>
<main>
{{ content_for_layout }}
</main>
<footer>
<!-- 页脚 -->
</footer>
</body>
</html>
实际应用场景
场景 1:不同设备使用不同布局
{% if params.device == "mobile" %}
{% layout "mobile" %}
{% elsif params.device == "tablet" %}
{% layout "tablet" %}
{% else %}
{% layout "desktop" %}
{% endif %}
<h1>响应式页面</h1>
场景 2:API 接口不使用布局
{% response_type "json" %}
{% layout none %}
{
"articles": [
{% for article in articles %}
{
"id": {{ article.id }},
"title": {{ article.title | json }}
}{% unless forloop.last %},{% endunless %}
{% endfor %}
]
}
场景 3:错误页面使用特殊布局
{% layout "error" %}
{% response_status 404 %}
<div class="error-page">
<h1>404 - 页面未找到</h1>
<p>抱歉,您访问的页面不存在。</p>
</div>
场景 4:打印页面使用简化布局
{% layout "print" %}
<h1>{{ page.title }}</h1>
<div class="content">
{{ page.body }}
</div>
注意事项
- 布局包装:使用布局时,模板内容会被包装在布局的
content_for_layout变量位置,而不是直接输出 - 禁用布局:使用
{% layout none %}时,模板内容会直接输出,不会被任何布局包装,此时模板需要包含完整的 HTML 结构(如果返回 HTML 格式) - 必须配合 response_type:当使用非 HTML 响应类型(如
turbo_stream、json、xml)时,必须禁用布局,避免布局的 HTML 结构影响响应格式 - 布局优先级:如果模板和布局中都设置了
response_type或response_status,布局中的设置会覆盖模板中的设置 - 标签顺序:将
layout标签放在模板的最前面,确保在渲染过程中正确设置布局 - 布局文件存在性:确保指定的布局文件存在于
layout/目录中,否则会使用默认布局或报错
常见错误
错误 1:非 HTML 响应未禁用布局
{%# ❌ 错误示例 %}
{% response_type "json" %}
<!-- 没有设置 layout none -->
{
"status": "success"
}
问题:响应会被布局的 HTML 结构包装,导致 JSON 解析失败。
解决:
{%# ✅ 正确示例 %}
{% response_type "json" %}
{% layout none %}
{
"status": "success"
}
错误 2:禁用布局但内容不完整
{%# ❌ 错误示例 %}
{% layout none %}
<h1>页面标题</h1>
<!-- 缺少完整的 HTML 结构 -->
问题:如果返回 HTML 格式,缺少完整的 HTML 结构可能导致页面显示异常。
解决:
{%# ✅ 正确示例 - 返回完整 HTML %}
{% layout none %}
<!DOCTYPE html>
<html>
<head>
<title>页面标题</title>
</head>
<body>
<h1>页面标题</h1>
</body>
</html>
或者使用布局:
{%# ✅ 正确示例 - 使用布局 %}
{% layout "theme" %}
<h1>页面标题</h1>
错误 3:布局文件不存在
{%# ❌ 错误示例 %}
{% layout "nonexistent" %}
<h1>页面标题</h1>
问题:如果指定的布局文件不存在,可能会使用默认布局或报错。
解决:确保布局文件存在于
layout/ 目录中,或使用存在的布局名称。最佳实践
- 非 HTML 响应禁用布局:当使用
response_type返回非 HTML 格式时,始终配合{% layout none %}禁用布局 - 标签顺序:将
layout标签放在模板的最前面,与其他控制标签(如response_type、response_status)一起 - 条件布局:根据设备、用户类型等条件动态选择布局,提供更好的用户体验
- 布局复用:创建通用的布局文件,减少重复代码
- 测试验证:确保在不同布局下页面显示正常,特别是响应式布局
总结
layout 标签用于控制模板的布局渲染,可以指定使用特定的布局文件,或者禁用布局。当需要返回非 HTML 格式的响应时,必须禁用布局以避免 HTML 结构污染响应内容。正确使用此标签可以实现灵活的页面布局控制和响应格式管理。