Chapter 10無料公開

領域の確保(Card): v-card

超Lチカ団編集局
超Lチカ団編集局
2024.01.11に更新

領域の確保(Card): v-card

v-card は Vuetify3 を使って Web ページのデザインをするときに使う、最も基本的な要素の一つです。カードは v-sheet と同様に、web ページの中に、一定の高さと幅を持った領域を確保する目的に使えます。

v-sheet との最大の違いは、v-card はお仕着せのスタイルが用意されている点です。自由なデザインがしたいときは v-sheet を使用し、お仕着せのデザインで(短時間で)デザインしたいときは v-card を使うと良いです。

基本

下記の画像は、v-card コンポーネントの基本構造を示しています(公式サイトの画像をそのまま引用したものです)。

image

  • 1: カード本体を示しています。
  • 2: カードのタイトルです。フォントの大きさや配置位置は自動的に決まります。
  • 3: カードのサブタイトルです。タイトルの下に自動的に配置されます。
  • 4: カード内部に配置するテキストです。
  • 5: ユーザが操作可能なボタンなどのコンポーネントです。

上記の要素の指定は、v-card の prop としてして指定する方法と、v-card-title, v-card-text などの子要素として指定する方法、v-slot で指定する方法の三通りがあります。いずれの場合でも、レンダリング(表示)結果はまったく同じになります。

image

下記コードは、子要素で指定した例です。v-card- で始まる名前の子要素は、基本的に配置順序を入れ替えてもデザインに影響しません。タイトルは常にカードの最上部に配置され、v-card-actions で指定したコンポーネントは常に最下部に配置されます。

<template>
  <v-container>
    <v-card class="w-50" elevation="4">
      <v-card-title>平家物語</v-card-title>
      <v-card-subtitle>作者不詳</v-card-subtitle>
      <v-card-text>
        祇園精舎の鐘の声、諸行無常の響きあり。
        娑羅双樹の花の色、盛者必衰の理をあらわす。
        おごれる人も久しからず、唯、春の夜の夢のごとし。
        猛きものもついにはほろびぬ、
        偏に風の前の塵に同じ。
      </v-card-text>
      <v-card-actions>
        <v-btn>源氏を選択</v-btn>
        <v-btn>平家を選択</v-btn>
      </v-card-actions>
    </v-card>
  </v-container>
</template>

下記コードは、prop で指定した例です。prop で指定するコンテキスト(文字列)が短い場合には、こちらのほうがシンプルに記述できます。なお v-card-actions は prop では指定できないため、子要素で指定しています。

<template>
  <v-container>
    <v-card class="w-50" elevation="4"
      title="平家物語"
      subtitle="作者不詳"
      text="祇園精舎の鐘の声、諸行無常の響きあり。
        娑羅双樹の花の色、盛者必衰の理をあらわす。
        おごれる人も久しからず、唯、春の夜の夢のごとし。
        猛きものもついにはほろびぬ、
        偏に風の前の塵に同じ。"
    >
      <v-card-actions>
        <v-btn>源氏を選択</v-btn>
        <v-btn>平家を選択</v-btn>
      </v-card-actions>
    </v-card>
  </v-container>
</template>

下記コードは v-slot を使用した例です。カード内部に複数のコンポーネントを配置する場合や、細かなデザインをしたい場合はこの方法が適しています。

<template>
  <v-container>
    <v-card class="w-50" elevation="4">
      <template v-slot:title>平家物語</template>
      <template v-slot:subtitle>作者不詳</template>
      <template v-slot:text>
        祇園精舎の鐘の声、諸行無常の響きあり。
        娑羅双樹の花の色、盛者必衰の理をあらわす。
        おごれる人も久しからず、唯、春の夜の夢のごとし。
        猛きものもついにはほろびぬ、
        偏に風の前の塵に同じ。
      </template>
      <template v-slot:actions>
        <v-btn>源氏を選択</v-btn>
        <v-btn>平家を選択</v-btn>
      </template>
    </v-card>
  </v-container>
</template>

外観の変更 (Variant)

variant prop を指定すると、大まかなデザイン(色、枠、影)の変更ができます。variant 名としては elevated, flat, tonal, outlined, text, plain の6種類を指定することができます。

image

  • evelated: 設定色で背景が塗りつぶされ、影が付きます。影の大きさは elevation で指定できます。
  • flat: 設定色で背景が塗りつぶされますが、影や枠はつきません。
  • tonal: 設定色の府透明度を下げた色で背景が塗りつぶされます。影や枠はつきません。
  • outlined: 背景は塗りつぶされません。代わりに設定色で枠がつきます。
  • text: 背景は塗りつぶされません。枠も影もつきません。
  • plain: ほぼ text と同じですが、マウスカーソルが上にないときは、色が全体的に薄く表示されます。

上の図では、わかりやすくするために v-btn にも同じ variant を指定してします。

<template>
  <v-container>
    <v-row>
      <v-col cols="4" v-for="val in variants">
        <v-card :variant="val">
          <v-card-title>平家物語</v-card-title>
          <v-card-subtitle>{{val}}</v-card-subtitle>
          <v-card-text>
            祇園精舎の鐘の声、諸行無常の響きあり。
            娑羅双樹の花の色、盛者必衰の理をあらわす。
            おごれる人も久しからず、唯、春の夜の夢のごとし。
            猛きものもついにはほろびぬ、
            偏に風の前の塵に同じ。
          </v-card-text>
          <v-card-actions>
            <v-btn :variant="val">源氏を選択</v-btn>
            <v-btn :variant="val">平家を選択</v-btn>
          </v-card-actions>
        </v-card>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  data: () => {
    return {
      variants: ['elevated','flat','tonal','outlined','text','plain']
    }
  }
}
</script>

image

上の図は color="tonal-darken-4" として色の設定の反映のされ方の違いを分かりやすくしたものです。色を指定すると flattext の違いがよくわかります。

仕切り線

水平方向の仕切り線には v-divider を使います。仕切り線は、v-card-text の上下の位置にのみ入れることができます(通常は)。v-divider で仕切り線を入れるときは、v-card-text または v-slot:text でテキスト部分を記述する必要があります。v-divider の配置される位置は、v-dividerv-card-text より前に記述されているか、後ろに記述されているかだけで決まります。

なお、text prop でテキストを記述して v-divider も配置すると、必ずテキストの真下の位置に仕切り線が配置されます。

image

<template>
  <v-container>
    <v-card class="w-50" elevation="4">
      <template v-slot:title>平家物語</template>
      <template v-slot:subtitle>作者不詳</template>
      <v-divider thickness="3"></v-divider>
      <v-card-text>
        祇園精舎の鐘の声、諸行無常の響きあり。
        娑羅双樹の花の色、盛者必衰の理をあらわす。
        おごれる人も久しからず、唯、春の夜の夢のごとし。
        猛きものもついにはほろびぬ、
        偏に風の前の塵に同じ。
      </v-card-text>
      <v-divider thickness="3"></v-divider>
      <template v-slot:actions>
        <v-btn>源氏を選択</v-btn>
        <v-btn>平家を選択</v-btn>
      </template>
    </v-card>
  </v-container>
</template>

画像関係

image prop で背景画像を指定できます。下の例では、文字が背景画像の暗い部分に重なることを防ぐために、マージンを指定して多少位置をずらしています。

image

<template>
  <v-container>
    <v-row>
      <v-col cols="4" v-for="val in variants">
        <v-card :variant="val" image="https://cdn.vuetifyjs.com/images/cards/docks.jpg">
          <v-card-title>平家物語</v-card-title>
          <v-card-subtitle>{{val}}</v-card-subtitle>
          <v-card-text>
            祇園精舎の鐘の声、諸行無常の響きあり。
            娑羅双樹の花の色、盛者必衰の理をあらわす。
            おごれる人も久しからず、唯、春の夜の夢のごとし。
            猛きものもついにはほろびぬ、
            偏に風の前の塵に同じ。
          </v-card-text>
          <v-divider class="mb-5"></v-divider>
          <v-card-actions class="mb-2">
            <v-btn :variant="val" color="white">源氏を選択</v-btn>
            <v-btn :variant="val" color="white">平家を選択</v-btn>
          </v-card-actions>
        </v-card>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  data: () => {
    return {
      variants: ['elevated','flat','tonal','outlined','text','plain']
    }
  }
}
</script>

image

背景画像が暗い場合には、theme="dark" を指定する方法も使えます。これを指定すると elevated, flat のときだけテキストの色が白になります。テキストや v-card-actions のコンポーネントの色を部分的に変えたい場合は、class="text-white"color="white" などとして直接色を指定する必要があります。

タイトルへのアイコンの追加

prepend-icon prop を使うと、タイトルの左側にアイコンを表示できます。
ただし、これを使うときは title, subtitle も prop で指定する必要か、もしくは v-slot で記述する必要があります。
アイコンの色を指定するなど、細かなスタイルの指定をしたいときは v-slot を使います。
なお、同様にして append-icon prop でタイトルの右側にアイコンを追加することもできます。

image

<template>
  <v-container>
    <v-row>
      <v-col cols="4">
        <v-card variant="elevated" 
          prepend-icon="mdi-book-open-variant"
          title="平家物語" subtitle="prop で指定した場合">
          <v-card-text>
            祇園精舎の鐘の声、諸行無常の響きあり。
            娑羅双樹の花の色、盛者必衰の理をあらわす。
            おごれる人も久しからず、唯、春の夜の夢のごとし。
            猛きものもついにはほろびぬ、
            偏に風の前の塵に同じ。
          </v-card-text>
          <v-card-actions>
            <v-btn>
            <v-icon icon="mdi-flag-outline" color="black" class="me-2"></v-icon>
              源氏を選択
            </v-btn>
            <v-btn>
              <v-icon icon="mdi-flag-variant" color="red-darken-4" class="me-2"></v-icon>
              平家を選択
            </v-btn>
          </v-card-actions>
        </v-card>
      </v-col>
      <v-col cols="4">
        <v-card variant="elevated">
          <template v-slot:prepend>
            <v-icon icon="mdi-book-open-variant" color="primary"></v-icon>
          </template>
          <template v-slot:title>
            平家物語
          </template>
          <template v-slot:subtitle>
            v-slot で指定した場合
          </template>
          <v-card-text>
            祇園精舎の鐘の声、諸行無常の響きあり。
            娑羅双樹の花の色、盛者必衰の理をあらわす。
            おごれる人も久しからず、唯、春の夜の夢のごとし。
            猛きものもついにはほろびぬ、
            偏に風の前の塵に同じ。
          </v-card-text>
          <v-card-actions>
            <v-btn>
            <v-icon icon="mdi-flag-outline" color="black" class="me-2"></v-icon>
              源氏を選択
            </v-btn>
            <v-btn>
              <v-icon icon="mdi-flag-variant" color="red-darken-4" class="me-2"></v-icon>
              平家を選択
            </v-btn>
          </v-card-actions>
        </v-card>
      </v-col>
    </v-row>
  </v-container>
</template>

入れ子のカード

v-card を入れ子にしたり、縦や横に並べるとデザインの幅が広がります。入れ子にした場合、親カードの色や variant などは子カードに継承されません。個別に指定する必要があります。

image

<template>
  <v-container>
    <v-row>
      <v-col cols="6">
        <v-card variant="elevated" elevation="5"
          color="indigo-darken-4" rounded="xl">
          <div class="d-flex justify-center">
            <v-card color="indigo-darken-4"
              class="w-50" variant="flat">
              <template v-slot:prepend>
                <v-icon icon="mdi-book-open-variant" color="blue-lighten-3"></v-icon>
              </template>
              <template v-slot:title>
                平家物語
              </template>
              <template v-slot:subtitle>
                v-slot で指定した場合
              </template>
              <v-card-text>
                祇園精舎の鐘の声、諸行無常の響きあり。
                娑羅双樹の花の色、盛者必衰の理をあらわす。
                おごれる人も久しからず、唯、春の夜の夢のごとし。
                猛きものもついにはほろびぬ、
                偏に風の前の塵に同じ。
              </v-card-text>
              <v-card-actions>
                <v-btn>
                <v-icon icon="mdi-flag-outline" color="white" class="me-2"></v-icon>
                  源氏を選択
                </v-btn>
                <v-btn>
                  <v-icon icon="mdi-flag-variant" color="red-darken-4" class="me-2"></v-icon>
                  平家を選択
                </v-btn>
              </v-card-actions>
            </v-card>
            <v-img src="https://cdn.vuetifyjs.com/images/cards/docks.jpg" class="me-4"></v-img>
          </div>
        </v-card>
      </v-col>
    </v-row>
  </v-container>
</template>

タイトルやボタンを中央や右に寄せる

タイトルとサブタイトルは <div class="d-flex justify-center"> とすれば寄せられます。v-card-actions の子要素は普通の方法では寄せらません。いくつか方法はありますが、下の例では v-layout で強引に寄せてみました。

左右のカードを見比べるとわかるのですが、カードの中のコンポーネントやテキストをデフォルト以外の方向に寄せると、寄せる方法によって微妙に縦方向のサイズに影響がでて、v-slot を使う場合と子要素を使う場合で高さが変わることがあります。

このようにお仕着せのデザインが気にらない場合は、v-card を使って強引にレイアウトするより、v-sheet を使って自力でレイアウトを指定したほうが幸せなことが多いです。

image

<template>
  <v-container>
    <v-row>
      <v-col>
        <v-card variant="elevated" elevation="4">
          <template v-slot:title>
            <div class="d-flex justify-center">作者不詳</div>
          </template>
          <template v-slot:subtitle>
            <div class="d-flex justify-center">中央寄せ</div>
          </template>
          <v-card-text>
            祇園精舎の鐘の声、諸行無常の響きあり。
            娑羅双樹の花の色、盛者必衰の理をあらわす。
            おごれる人も久しからず、唯、春の夜の夢のごとし。
            猛きものもついにはほろびぬ、
            偏に風の前の塵に同じ。
          </v-card-text>
          <template v-slot:actions>
            <v-layout>
              <v-spacer></v-spacer>
              <v-btn>源氏を選択</v-btn>
              <v-btn>平家を選択</v-btn>
              <v-spacer></v-spacer>
            </v-layout>
          </template>
        </v-card>
      </v-col>
      <v-col>
        <v-card variant="elevated" elevation="4">
          <v-card-title>
            <div class="d-flex justify-end">平家物語</div>
          </v-card-title>
          <v-card-subtitle>
            <div class="d-flex justify-end">右寄せ</div>
          </v-card-subtitle>
          <v-card-text>
            祇園精舎の鐘の声、諸行無常の響きあり。
            娑羅双樹の花の色、盛者必衰の理をあらわす。
            おごれる人も久しからず、唯、春の夜の夢のごとし。
            猛きものもついにはほろびぬ、
            偏に風の前の塵に同じ。
          </v-card-text>
          <v-card-actions>
            <v-layout>
              <v-spacer></v-spacer>
              <v-btn>源氏を選択</v-btn>
              <v-btn>平家を選択</v-btn>
            </v-layout>
          </v-card-actions>
        </v-card>
      </v-col>
    </v-row>
  </v-container>
</template>

v-cardvariant, prop については下記を見てください。