Layout レイアウト - Vant 4
Layout レイアウト
📐 紹介
Layout レイアウトコンポーネントは経験豊富な建築家のようなもので、あなたのページに堅牢で柔軟な骨組みを構築します 🏗️!van-row と van-col という黄金コンビを使えば、様々な複雑なページレイアウトを簡単に構築できます。Row は家の横梁のように、水平方向の全体的な計画を担当します。Col は丁寧に設計された部屋のように、サイズと位置を自由に調整できます。24列のグリッドシステムにより、ミリ単位まで正確なレイアウトコントロールが可能になり、シンプルな2カラムレイアウトから複雑なマルチカラム構造まで、手軽に実現できます ✨。
📦 導入
以下の方法でグローバルにコンポーネントを登録します。詳細な登録方法についてはコンポーネントの登録を参照してください。
import { createApp } from'vue'; import { Col, Row } from'vant'; const app = createApp(); app.use(Col); app.use(Row);🎯 コード例
基本的な使い方
24列グリッドシステムは精密な定規のように、あなたのレイアウトに無限の可能性を提供します 📏!Col に span 属性を設定することで、各列の幅の割合を正確に制御できます。まるでキャンバス上で自由にスペースを割り当てるかのようです。offset 属性は思いやりのあるスペーサーのように、余白や位置ずれ効果を簡単に作り出し、レイアウトに層感と呼吸感を与えます!
列要素の間隔を設定
空間の芸術は程よい余白にあります 🎨!gutter 属性はレイアウトの呼吸空間のようで、適切な間隔を設定することで、各列要素間に優雅な距離を保つことができます。音楽の休符のように、これらの間隔によってレイアウト全体がより調和のとれたものになり、要素間の混雑感を避けます!
垂直方向の間隔
時には水平方向の間隔だけでなく、垂直方向の呼吸空間も必要です 🌬️!配列形式の gutter 設定を使用すると、水平方向と垂直方向の両方の間隔を同時に制御できます。まるでレイアウトに立体感を加えるかのようで、ページは平面的な並びではなく、空間の階層を持つようになります!
整列方法
整列はレイアウト美学の本質です ✨!justify 属性はプロのタイポグラファーのように、コンテンツが主軸上でどのように分布するかを正確に制御します。左揃えの厳格さ、中央揃えのバランス、両端揃えの充実感など、さまざまな視覚効果と感情表現をレイアウトに与えることができます!
API
Row Props
| パラメータ | 説明 | タイプ | デフォルト値 |
|---|---|---|---|
| gutter | 列要素間の間隔(単位は px) | number | string | Array | - |
| tag | カスタム要素タグ | string | div |
| justify | 主軸の整列方法、end``center``space-around``space-between から選択可能 | string | start |
| align | 交差軸の整列方法、center``bottom から選択可能 | string | top |
| wrap | 自動で折り返すかどうか | boolean | true |
Col Props
| パラメータ | 説明 | タイプ | デフォルト値 |
|---|---|---|---|
| span | 列要素の幅 | number | string | - |
| offset | 列要素のオフセット距離 | number | string | - |
| tag | カスタム要素タグ | string | div |
Row Events
| イベント名 | 説明 | コールバックパラメータ |
|---|---|---|
| click | クリックしたときに発生 | event: MouseEvent |
Col Events
| イベント名 | 説明 | コールバックパラメータ |
|---|---|---|
| click | クリックしたときに発生 | event: MouseEvent |
型定義
コンポーネントは以下の型定義をエクスポートしています:
importtype { ColProps, RowProps, RowAlign, RowJustify } from'vant';ベストプラクティス
グリッドシステムの設計原則
レスポンシブレイアウトを設計する際は、以下の原則に従うことをお勧めします 📐:
<!-- ✅ 推奨:合理的なグリッド分配 -->
<van-row :gutter="20">
<van-col :span="8">主要コンテンツ</van-col>
<van-col :span="16">サブコンテンツ</van-col>
</van-row>
<!-- ❌ 避ける:不合理なグリッド分配 -->
<van-row>
<van-col :span="23">コンテンツが広すぎる</van-col>
<van-col :span="1">コンテンツが狭すぎる</van-col>
</van-row>レスポンシブレイアウト戦略
<!-- モバイルファーストのレスポンシブデザイン -->
<van-row :gutter="[16, 16]">
<van-col
:span="24"
:class="{ 'desktop-half': isDesktop }"
>
<div class="content-block">コンテンツ領域</div>
</van-col>
</van-row>
<style>
@media (min-width: 768px) {
.desktop-half {
flex: 0 0 50% !important;
max-width: 50% !important;
}
}
</style>ネストレイアウトのベストプラクティス
<!-- 複雑なレイアウトのネスト使用 -->
<van-row :gutter="20">
<van-col :span="16">
<van-row :gutter="10">
<van-col :span="12">子コンテンツ1</van-col>
<van-col :span="12">子コンテンツ2</van-col>
</van-row>
</van-col>
<van-col :span="8">サイドバー</van-col>
</van-row>パフォーマンス最適化のヒント
不要な再レンダリングを減らす
レイアウトコンポーネントのパフォーマンスを最適化しましょう 🚀:
// ✅ 推奨:計算プロパティを使用してレスポンシブレイアウトを最適化
const layoutConfig = computed(() => {
if (screenWidth.value < 768) {
return { span: 24, gutter: 16 };
} else if (screenWidth.value < 1200) {
return { span: 12, gutter: 20 };
} else {
return { span: 8, gutter: 24 };
}
});
// テンプレートで使用
<van-row :gutter="layoutConfig.gutter">
<van-col :span="layoutConfig.span">
コンテンツ
</van-col>
</van-row>深すぎるネストを避ける
<!-- ✅ 推奨:扁平化されたレイアウト構造 -->
<van-row :gutter="20">
<van-col :span="8">コンテンツ1</van-col>
<van-col :span="8">コンテンツ2</van-col>
<van-col :span="8">コンテンツ3</van-col>
</van-row>
<!-- ❌ 避ける:深すぎるネスト階層 -->
<van-row>
<van-col :span="24">
<van-row>
<van-col :span="24">
<van-row>
<van-col :span="24">コンテンツ</van-col>
</van-row>
</van-col>
</van-row>
</van-col>
</van-row>デザインアドバイス
視覚階層
- 主従関係を明確に:異なる列幅を使用して重要なコンテンツを強調 📊
- 間隔の統一:一貫した間隔の規範を維持 📏
- 整列の整頓:要素が整った美しさを確保 📐
- 余白の合理性:適切な余白でレイアウトに呼吸を与える 🌬️
レスポンシブデザイン
- モバイルファースト:小さなスクリーンから設計を開始し、段階的に大きなスクリーンに適応 📱
- 適切なブレークポイント:適切なレスポンシブブレークポイントを選択 💻
- コンテンツの適応:コンテンツが様々なスクリーンで良好に表示されることを確認 🖥️
よくある質問と解決策
Q: 高さが等しくない列を下部揃えにするには?
<van-row align="bottom" :gutter="20">
<van-col :span="8">
<div class="content-box">
<p>短いコンテンツ</p>
</div>
</van-col>
<van-col :span="8">
<div class="content-box">
<p>これは比較的長いコンテンツです</p>
<p>複数行のテキストを含みます</p>
</div>
</van-col>
<van-col :span="8">
<div class="content-box">
<p>中程度の長さのコンテンツ</p>
</div>
</van-col>
</van-row>
<style>
.content-box {
height: 100%;
display: flex;
flex-direction: column;
justify-content: flex-end;
}
</style>Q: レスポンシブなグリッドレイアウトを実装するには?
// コンポジションAPIを使用してレスポンシブレイアウトを実装
import { ref, computed, onMounted, onUnmounted } from 'vue';
export default {
setup() {
const screenWidth = ref(window.innerWidth);
const updateScreenWidth = () => {
screenWidth.value = window.innerWidth;
};
const colSpan = computed(() => {
if (screenWidth.value < 576) return 24; // スマホ
if (screenWidth.value < 768) return 12; // タブレット縦
if (screenWidth.value < 992) return 8; // タブレット横
if (screenWidth.value < 1200) return 6; // 小さなデスクトップ
return 4; // 大きなデスクトップ
});
onMounted(() => {
window.addEventListener('resize', updateScreenWidth);
});
onUnmounted(() => {
window.removeEventListener('resize', updateScreenWidth);
});
return { colSpan };
}
};Q: 動的なグリッド間隔を実装するには?
<template>
<div>
<van-slider
v-model="gutterValue"
:min="0"
:max="40"
@change="handleGutterChange"
/>
<van-row :gutter="dynamicGutter">
<van-col :span="8">コンテンツ1</van-col>
<van-col :span="8">コンテンツ2</van-col>
<van-col :span="8">コンテンツ3</van-col>
</van-row>
</div>
</template>
<script>
const gutterValue = ref(20);
const dynamicGutter = computed(() => [gutterValue.value, gutterValue.value]);
const handleGutterChange = (value) => {
console.log('間隔が変更されました:', value);
};
</script>高度な使い方の例
カード式レイアウト
<template>
<van-row :gutter="[16, 16]">
<van-col
v-for="card in cardList"
:key="card.id"
:span="cardSpan"
>
<div class="card-container">
<div class="card-header">{{ card.title }}</div>
<div class="card-content">{{ card.content }}</div>
<div class="card-footer">{{ card.date }}</div>
</div>
</van-col>
</van-row>
</template>
<style>
.card-container {
background: #fff;
border-radius: 8px;
padding: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
height: 100%;
display: flex;
flex-direction: column;
}
.card-header {
font-weight: bold;
margin-bottom: 12px;
}
.card-content {
flex: 1;
color: #666;
line-height: 1.5;
}
.card-footer {
margin-top: 12px;
font-size: 12px;
color: #999;
}
</style>ダッシュボードレイアウト
<template>
<div class="dashboard">
<!-- 上部統計領域 -->
<van-row :gutter="20" class="stats-row">
<van-col :span="6" v-for="stat in stats" :key="stat.id">
<div class="stat-card">
<div class="stat-value">{{ stat.value }}</div>
<div class="stat-label">{{ stat.label }}</div>
</div>
</van-col>
</van-row>
<!-- 主要コンテンツ領域 -->
<van-row :gutter="20" class="content-row">
<van-col :span="16">
<div class="chart-container">
<!-- チャートコンポーネント -->
</div>
</van-col>
<van-col :span="8">
<div class="sidebar-container">
<!-- サイドバーコンテンツ -->
</div>
</van-col>
</van-row>
</div>
</template>関連コンポーネント
- Space スペース - コンポーネント間の間隔を設定
- Divider 分割線 - コンテンツを区切る分割線
- Grid グリッド - グリッドレイアウトコンポーネント
- Sticky スティッキーレイアウト - スティッキーポジショニングレイアウト