Applied NuxtImg to pages and components

This commit is contained in:
2024-12-07 23:29:20 +09:00
parent 3ddcf5fa5e
commit e821b258c3
13 changed files with 264 additions and 170 deletions

View File

@@ -1,111 +1,133 @@
<script setup lang="ts"> <script setup lang="ts">
import type { LinkCardProperty } from "~/utils/types/linkCard"; import type { LinkCardProperty } from "~/utils/types/linkCard";
const property = defineProps<LinkCardProperty>(); const property = defineProps<LinkCardProperty>();
const doesNotHaveImage = ref<boolean>(property.imagePath === undefined); const { backgroundImageStyles } = useBackgroundImageOptimization();
const imagePath =
property.imagePath === undefined || property.imagePath === ""
? "/sera-logo-text.svg"
: (property.imagePath as string);
const optimizeImage = (backgroundImagePath: string) => {
backgroundImageStyles.value = backgroundImagePath;
return backgroundImageStyles.value;
};
</script> </script>
<template> <template>
<NuxtLink :to="property.link" :class="{ withoutImage: doesNotHaveImage }"> <div class="card-wrapper">
<div <NuxtLink :to="property.link" class="card">
class="image" <div class="image">
v-if="property.imagePath" <div :style="optimizeImage(imagePath)"></div>
:style="{ backgroundImage: `url(${property.imagePath})` }" </div>
></div> <div class="texts">
<h2>{{ property.title }}</h2> <h2>{{ property.title }}</h2>
<p>{{ property.description }}</p> <p>{{ property.description }}</p>
</NuxtLink> </div>
</NuxtLink>
</div>
</template> </template>
<style scoped> <style scoped>
a { .card-wrapper {
container: link-card / inline-size;
}
@property --minimum-card-width {
syntax: "<length>";
inherits: false;
initial-value: 320px;
}
@property --minimum-card-height {
syntax: "<length>";
inherits: false;
initial-value: 16rem;
}
@property --card-padding-inline {
syntax: "<length>";
inherits: false;
initial-value: 1rem;
}
@property --card-padding-vertical {
syntax: "<length>";
inherits: false;
initial-value: 0.75rem;
}
.card {
display: grid; display: grid;
width: 25rem;
height: clamp(10rem, 15vh, max(30rem, fit-content));
grid: 2fr 1fr 1.5fr / 1fr;
background-color: var(--starlight);
border-radius: 1rem;
text-decoration: none;
transition: scale 0.2s ease-in-out;
}
a:hover {
scale: 105%;
transition: scale 0.2s ease-in-out;
}
a > * {
margin: 0 2rem;
}
.withoutImage {
grid: 1fr 1.5fr / 1fr;
}
.image {
background-repeat: no-repeat;
background-position: center;
background-size: cover;
width: 18rem;
height: 12rem;
margin-top: 1.75rem;
margin-bottom: 0.75rem;
place-self: center;
}
h2 {
position: relative; position: relative;
color: var(--neptune1); grid-template-areas: "image texts";
background-color: var(--starlight5);
border-radius: 1rem; border-radius: 1rem;
margin: 0.75rem 2rem; box-shadow: 10px 5px 5px var(--starlight1);
padding: 1rem 1.75rem; background-color: var(--starlight);
align-self: center; min-width: calc(var(--minimum-card-width) - 2 * var(--card-padding-inline));
line-height: 2rem; min-height: calc(
font-size: clamp(16pt, 3vw, 20pt); var(--minimum-card-height) - 2 * var(--card-padding-vertical)
} );
padding: var(--card-padding-vertical) var(--card-padding-inline);
h2::after { transition: all 0.3s ease-in-out;
display: block; text-decoration: none;
content: ""; aspect-ratio: 5 / 2;
position: absolute; &:hover {
width: 7px; scale: 105%;
height: max(2rem, 60%); transition: all 0.3s ease-in-out;
top: 50%;
left: 0.75rem;
transform: translateY(-50%);
background-color: var(--neptune1);
border-radius: 3px;
}
p {
color: var(--deep-space);
margin: 0 2rem;
}
@media screen and (max-width: 1024px) {
a {
width: 20rem;
}
a > * {
margin: unset 0.25rem;
}
.image {
width: 16rem;
height: 10rem;
} }
} }
@media screen and (max-width: 640px) { .card > .image {
a { grid-area: image;
width: 16rem; min-width: 128px;
width: 30cqw;
align-content: center;
& > div {
aspect-ratio: 1 / 1;
background: inherit;
background-repeat: no-repeat;
background-position: center;
background-attachment: local;
background-size: cover;
border-radius: 1rem;
margin-inline: 0.75rem;
} }
a > * { }
margin: unset 0.75rem;
.card > .texts {
grid-area: texts;
margin-inline: 0.75rem;
height: 50cqw;
width: 60cqw;
& > h2 {
color: var(--ocean-blue);
height: 15cqw;
margin-bottom: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
align-content: center;
} }
.image { & > p {
width: 12rem; color: var(--deep-space);
height: 8rem; height: 25cqw;
margin-top: 0.75rem; margin-top: 0;
overflow: hidden;
text-overflow: ellipsis;
}
}
@container link-card (width < 28rem) {
.card {
padding: 0.5rem 0;
}
.card > .image {
min-width: 96px;
}
.card > .texts > p {
height: 75px;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
} }
} }
</style> </style>

View File

@@ -1,9 +1,24 @@
<script setup lang="ts"> <script setup lang="ts">
import type { NewsCardProperty } from "~/utils/types/newsCard"; import type { NewsCardProperty } from "~/utils/types/newsCard";
import DOMPurify from "isomorphic-dompurify";
import { marked } from "marked"; import { marked } from "marked";
const { backgroundImageStyles } = useBackgroundImageOptimization();
const optimizeImage = (backgroundImagePath: string) => {
backgroundImageStyles.value = backgroundImagePath;
return backgroundImageStyles.value;
};
const property = defineProps<NewsCardProperty>(); const property = defineProps<NewsCardProperty>();
const newsTypeText = ref<string>(
property.newsEntry.entryType === EntryType.Article ? "記事" : "お知らせ"
);
const isArticle = computed(() => {
return property.newsEntry.entryType === EntryType.Article;
});
const datePosted = new Date( const datePosted = new Date(
property.newsEntry.date as number property.newsEntry.date as number
).toLocaleDateString("ja-JP", { dateStyle: "medium" }); ).toLocaleDateString("ja-JP", { dateStyle: "medium" });
@@ -16,41 +31,32 @@ const coverImagePath = ref<string>(
</script> </script>
<template> <template>
<div <div class="news-card" :style="optimizeImage(coverImagePath)">
class="news-card"
:style="{ backgroundImage: `url(${coverImagePath})` }"
>
<NuxtLink <NuxtLink
class="card-content" class="card-content"
:to="property.newsEntry.linkPath" v-bind:data-type="property.newsEntry.entryType"
v-if=" :to="property.newsEntry.linkPath || ''"
property.newsEntry.linkPath !== null &&
property.newsEntry.entryType === EntryType.Article
"
> >
<p class="news-type article">記事</p> <p
class="news-type"
:class="{ article: isArticle, tweet: !isArticle }"
>
{{ newsTypeText }}
</p>
<p class="new" v-if="property.isNew">NEW!</p> <p class="new" v-if="property.isNew">NEW!</p>
<div class="content"> <div class="content">
<article <article
v-html=" v-html="
marked.parse(property.newsEntry.cardContent as string) DOMPurify.sanitize(
marked.parse(
property.newsEntry.cardContent as string
) as string
)
" "
></article> ></article>
</div> </div>
<small>{{ datePosted }}</small> <small>{{ datePosted }}</small>
</NuxtLink> </NuxtLink>
<div class="card-content" v-else>
<p class="news-type tweet">お知らせ</p>
<p class="new" v-if="property.isNew">NEW!</p>
<div class="content">
<article
v-html="
marked.parse(property.newsEntry.cardContent as string)
"
></article>
</div>
<small>{{ datePosted }}</small>
</div>
</div> </div>
</template> </template>
@@ -66,6 +72,12 @@ const coverImagePath = ref<string>(
background-position: center; background-position: center;
background-attachment: local; background-attachment: local;
background-size: cover; background-size: cover;
transition: all 0.3s ease-in-out;
&:has(a[data-type="0"]):hover {
scale: 105%;
filter: grayscale(25%);
transition: all 0.3s ease-in-out;
}
} }
.card-content { .card-content {
@@ -78,36 +90,31 @@ const coverImagePath = ref<string>(
right: 0; right: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
background-color: rgba(255, 255, 255, 0.15); background-color: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(5px) brightness(55%); backdrop-filter: blur(5px) brightness(55%);
color: var(--starlight); color: var(--starlight);
text-decoration: none; text-decoration: none;
} }
.card-content .content { .card-content > .content {
font-size: larger; font-size: larger;
font-weight: 400; font-weight: 400;
margin-top: 2.75rem; margin-top: 2.75rem;
} }
.card-content article, .content > article {
.card-content img {
margin: 0 1rem; margin: 0 1rem;
} }
.card-content img { .content > article :deep(a) {
margin-top: 3rem; font-weight: 600;
width: 10rem; color: var(--neptune2);
height: auto; &:visited {
padding: 0.25rem; color: var(--neptune2);
margin-left: 1.75rem; }
} }
.card-content img[src="/sera-logo-text.svg"] { .card-content > .news-type {
background-color: var(--starlight);
}
.card-content .news-type {
position: absolute; position: absolute;
margin: 0; margin: 0;
padding-top: 0.25rem; padding-top: 0.25rem;
@@ -119,17 +126,17 @@ const coverImagePath = ref<string>(
border-bottom-right-radius: 1rem; border-bottom-right-radius: 1rem;
} }
.card-content .tweet { .card-content > .tweet {
background-color: var(--venus2); background-color: var(--venus2);
color: var(--venus1); color: var(--venus1);
} }
.card-content .article { .card-content > .article {
background-color: var(--venus1); background-color: var(--venus1);
color: var(--astronaut); color: var(--astronaut);
} }
.card-content .new { .card-content > .new {
position: absolute; position: absolute;
margin: 0; margin: 0;
right: 0; right: 0;
@@ -144,7 +151,7 @@ const coverImagePath = ref<string>(
border-bottom-left-radius: 1rem; border-bottom-left-radius: 1rem;
} }
.card-content small { .card-content > small {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
right: 0; right: 0;

View File

@@ -2,10 +2,13 @@
import type { PageTopProperty } from "~/utils/types/pageTop"; import type { PageTopProperty } from "~/utils/types/pageTop";
const property = defineProps<PageTopProperty>(); const property = defineProps<PageTopProperty>();
const backgroundImageOptimizer = useBackgroundImageOptimization();
backgroundImageOptimizer.backgroundImageStyles.value = property.imagePath;
</script> </script>
<template> <template>
<div :style="{ backgroundImage: `url(${property.imagePath})` }"> <div :style="backgroundImageOptimizer.backgroundImageStyles.value">
{{ property.text }} {{ property.text }}
</div> </div>
</template> </template>

View File

@@ -1,8 +1,16 @@
<script setup lang="ts"> <script setup lang="ts">
import type { SlideProperty, SlideEntry } from "~/utils/types/slide.ts"; import type { SlideProperty, SlideEntry } from "~/utils/types/slide.ts";
import DOMPurify from "isomorphic-dompurify";
import { marked } from "marked";
const property = defineProps<SlideProperty>(); const property = defineProps<SlideProperty>();
const { viewPortOrientation } = useWindowDimensions(); const { backgroundImageStyles } = useBackgroundImageOptimization();
const optimizeImage = (backgroundImagePath: string) => {
backgroundImageStyles.value = backgroundImagePath;
return backgroundImageStyles.value;
};
const UnitREM = 16; const UnitREM = 16;
const fourREM = 4 * UnitREM; const fourREM = 4 * UnitREM;
@@ -169,15 +177,20 @@ onUnmounted(() => {
<li <li
v-for="(entry, index) in property.entries" v-for="(entry, index) in property.entries"
:key="index" :key="index"
:style="{ :style="optimizeImage(entry.imagePath)"
backgroundImage: `url('${entry.imagePath}')`,
}"
v-show="currentSlide === index" v-show="currentSlide === index"
class="slide" class="slide"
> >
<div class="content"> <div class="content">
<h1>{{ entry.title }}</h1> <h1>{{ entry.title }}</h1>
<p>{{ entry.content }}</p> <div
class="rendered-paragraph"
v-html="
DOMPurify.sanitize(
marked.parse(entry.content) as string
)
"
></div>
<NuxtLink :to="entry.link" v-if="entry.link"> <NuxtLink :to="entry.link" v-if="entry.link">
詳しくはコチラ 詳しくはコチラ
</NuxtLink> </NuxtLink>
@@ -192,7 +205,7 @@ onUnmounted(() => {
class="preview" class="preview"
@click="handelClick(entry)" @click="handelClick(entry)"
> >
<img :src="entry.imagePath" alt="slide image preview" /> <NuxtImg :src="entry.imagePath" alt="slide image preview" />
<svg <svg
width="72" width="72"
height="72" height="72"
@@ -257,14 +270,25 @@ ul {
text-align: center; text-align: center;
color: var(--starlight); color: var(--starlight);
} }
& > p { & > :deep(.rendered-paragraph) p {
height: 3rem; height: 3rem;
margin: 0;
justify-self: center; justify-self: center;
color: var(--starlight); color: var(--starlight);
font-size: clamp(14pt, 1.5cqw, 24pt); font-size: clamp(14pt, 1.5cqw, 24pt);
font-weight: 600; font-weight: 600;
text-align: center; text-align: center;
} }
& > :deep(.rendered-paragraph) a {
color: var(--neptune2);
&:visited {
color: var(--neptune2);
}
}
& > .rendered-paragraph {
height: 3rem;
margin: 1.5rem 0;
}
& > a { & > a {
width: fit-content; width: fit-content;
border: var(--starlight) 3px solid; border: var(--starlight) 3px solid;
@@ -375,9 +399,4 @@ ul {
margin: calc(1rem / 16) 0; margin: calc(1rem / 16) 0;
} }
} }
.portrait-controler {
flex-direction: column;
right: 0rem;
}
</style> </style>

View File

@@ -0,0 +1,30 @@
/**
* Vue Composable for optimizing image used in background-image.
* @module composables/backgroundImageOptimization
*/
/**
* Vue Composable for optimizing background-image with Nuxt Image
* @returns { WritableComputedRef<{ backgroundImage: string}, string>} writable computed value that will return the Vue style object with optimized image URL
*/
function useBackgroundImageOptimization() {
const targetImage = ref("");
const img = useImage();
const backgroundImageStyles = computed({
get: () => {
const imageURL = img(targetImage.value, {
format: "webp",
quality: 80,
});
return { backgroundImage: `url("${imageURL}")` };
},
set: (value: string) => {
targetImage.value = value;
},
});
return { backgroundImageStyles };
}
export { useBackgroundImageOptimization };

View File

@@ -28,7 +28,7 @@ useSeoMeta(
</section> </section>
<section> <section>
<img <NuxtImg
src="/images/koshien2020_mission-rogo.png" src="/images/koshien2020_mission-rogo.png"
alt="2020 Mission Logo" alt="2020 Mission Logo"
class="float-right" class="float-right"
@@ -58,7 +58,7 @@ useSeoMeta(
<section> <section>
<h3>種子島ロケットコンテスト</h3> <h3>種子島ロケットコンテスト</h3>
<h4>滑空定点回収</h4> <h4>滑空定点回収</h4>
<img <NuxtImg
src="/images/rocket_top.jpg" src="/images/rocket_top.jpg"
alt="rockets" alt="rockets"
class="float-right" class="float-right"
@@ -93,7 +93,7 @@ useSeoMeta(
</ul> </ul>
<br /> <br />
<h4>CanSat</h4> <h4>CanSat</h4>
<img <NuxtImg
src="/images/cansat/cansat_03.jpg" src="/images/cansat/cansat_03.jpg"
alt="Sample Image" alt="Sample Image"
class="float-right" class="float-right"
@@ -145,7 +145,7 @@ useSeoMeta(
<section> <section>
<h2>その他活動実績 (イベントなど)</h2> <h2>その他活動実績 (イベントなど)</h2>
<img <NuxtImg
src="/images/uchu_fea.jpg" src="/images/uchu_fea.jpg"
alt="Sample Image" alt="Sample Image"
class="float-right" class="float-right"

View File

@@ -63,7 +63,7 @@ useSeoMeta(
:key="entry.id" :key="entry.id"
> >
<figure> <figure>
<img :src="entry.imagePath" :alt="entry.caption" /> <NuxtImg :src="entry.imagePath" :alt="entry.caption" />
<figcaption>{{ entry.caption }}</figcaption> <figcaption>{{ entry.caption }}</figcaption>
</figure> </figure>
</div> </div>
@@ -73,7 +73,7 @@ useSeoMeta(
<button @click="closeViewer" class="close"> <button @click="closeViewer" class="close">
<Icon name="ic:baseline-close" /> <Icon name="ic:baseline-close" />
</button> </button>
<img :src="imagePathViewer" :alt="captionViewer" /> <NuxtImg :src="imagePathViewer" :alt="captionViewer" />
<p>{{ captionViewer }}</p> <p>{{ captionViewer }}</p>
<button @click="changeImage(Direction.FORWARD)" class="next"> <button @click="changeImage(Direction.FORWARD)" class="next">
<Icon name="material-symbols:arrow-forward-rounded" /> <Icon name="material-symbols:arrow-forward-rounded" />
@@ -163,6 +163,7 @@ main {
grid-area: caption; grid-area: caption;
justify-self: center; justify-self: center;
align-self: flex-end; align-self: flex-end;
margin-inline: 1.25rem;
} }
.image-viewer .close { .image-viewer .close {

View File

@@ -15,7 +15,11 @@ useSeoMeta(
<PankuzuList current-page-name="SERAについて" /> <PankuzuList current-page-name="SERAについて" />
<main> <main>
<section> <section>
<img src="/sera-logo-text.svg" alt="SERA Logo" class="float-left" /> <NuxtImg
src="/sera-logo-text.svg"
alt="SERA Logo"
class="float-left"
/>
<p> <p>
宇宙分野に興味ある学生が集い宇宙理工学に関する知識を身に付けると共に宇宙分野に関連する各種競技会へ参加して人間力と実践力を養うことを目的に活動しています 宇宙分野に興味ある学生が集い宇宙理工学に関する知識を身に付けると共に宇宙分野に関連する各種競技会へ参加して人間力と実践力を養うことを目的に活動しています
</p> </p>

View File

@@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import DOMPurify from "isomorphic-dompurify";
import { marked } from "marked"; import { marked } from "marked";
const route = useRoute(); const route = useRoute();
@@ -30,9 +31,10 @@ onMounted(() => {
postedDateElement.textContent = "掲載日: " + postedDate; postedDateElement.textContent = "掲載日: " + postedDate;
articleTitle?.insertAdjacentElement("afterend", postedDateElement); articleTitle?.insertAdjacentElement("afterend", postedDateElement);
const cardContentConversion = document.createElement("div"); const cardContentConversion = document.createElement("div");
cardContentConversion.innerHTML = marked.parse( const purifiedHTML = DOMPurify.sanitize(
data.value?.cardContent as string marked.parse(data.value?.cardContent as string) as string
) as string; );
cardContentConversion.innerHTML = purifiedHTML;
useSeoMeta( useSeoMeta(
generateSeoMeta( generateSeoMeta(
articleTitle?.innerText as string, articleTitle?.innerText as string,
@@ -48,11 +50,17 @@ onMounted(() => {
<PageTop text="News" image-path="/images/news-top.jpg" /> <PageTop text="News" image-path="/images/news-top.jpg" />
<PankuzuList :current-page-name="pankuzuListPageName()" /> <PankuzuList :current-page-name="pankuzuListPageName()" />
<main> <main>
<img :src="(data?.coverImagePath as string) || '/sera-logo-text.svg'" /> <NuxtImg
:src="(data?.coverImagePath as string) || '/sera-logo-text.svg'"
/>
<div <div
id="article" id="article"
class="markdown" class="markdown"
v-html="marked.parse(data?.article as string)" v-html="
DOMPurify.sanitize(
marked.parse(data?.article as string) as string
)
"
></div> ></div>
</main> </main>
</template> </template>

View File

@@ -13,7 +13,7 @@ useSeoMeta(
<PankuzuList current-page-name="CanSat開発チーム" /> <PankuzuList current-page-name="CanSat開発チーム" />
<main> <main>
<section> <section>
<img <NuxtImg
src="/images/cansat_top.jpg" src="/images/cansat_top.jpg"
alt="CanSat top image" alt="CanSat top image"
class="float-left" class="float-left"
@@ -29,7 +29,7 @@ useSeoMeta(
<section> <section>
<h2>CanSatとは</h2> <h2>CanSatとは</h2>
<img <NuxtImg
src="/images/cansat/cansat_01.jpg" src="/images/cansat/cansat_01.jpg"
alt="CanSat" alt="CanSat"
class="float-right" class="float-right"
@@ -52,7 +52,7 @@ useSeoMeta(
<section> <section>
<h2>CanSat開発チームの活動</h2> <h2>CanSat開発チームの活動</h2>
<img <NuxtImg
src="/images/cansat/cansat_02.jpg" src="/images/cansat/cansat_02.jpg"
alt="SERA自作ロケット" alt="SERA自作ロケット"
class="float-left" class="float-left"
@@ -74,7 +74,7 @@ useSeoMeta(
<section> <section>
<h3>缶サット甲子園</h3> <h3>缶サット甲子園</h3>
<img <NuxtImg
src="/images/cansat/koshien2020.jpg" src="/images/cansat/koshien2020.jpg"
alt="缶サット甲子園" alt="缶サット甲子園"
class="float-right" class="float-right"
@@ -92,7 +92,7 @@ useSeoMeta(
<section> <section>
<h3>種子島ロケットコンテスト</h3> <h3>種子島ロケットコンテスト</h3>
<img <NuxtImg
src="/images/cansat/seratank-1.png" src="/images/cansat/seratank-1.png"
alt="SERATANK-1" alt="SERATANK-1"
class="float-left" class="float-left"

View File

@@ -30,7 +30,7 @@ useSeoMeta(
<section> <section>
<h3>AlphaⅢ</h3> <h3>AlphaⅢ</h3>
<img <NuxtImg
src="/images/rocket/alpha3.jpg" src="/images/rocket/alpha3.jpg"
alt="Alpha III" alt="Alpha III"
class="float-left" class="float-left"
@@ -44,7 +44,7 @@ useSeoMeta(
<section> <section>
<h3>Raspberry Pi</h3> <h3>Raspberry Pi</h3>
<img <NuxtImg
src="/images/education/raspberry-pi-4.jpg" src="/images/education/raspberry-pi-4.jpg"
alt="Raspberry Pi 4" alt="Raspberry Pi 4"
class="float-right" class="float-right"
@@ -79,7 +79,7 @@ useSeoMeta(
<section> <section>
<h2>教育用ローバーの開発</h2> <h2>教育用ローバーの開発</h2>
<img <NuxtImg
src="/images/education/education-1.jpg" src="/images/education/education-1.jpg"
alt="教育用ローバー" alt="教育用ローバー"
class="float-left" class="float-left"

View File

@@ -68,7 +68,7 @@ useSeoMeta(
</section> </section>
<section> <section>
<img src="/images/kosen1_gunma-cgv5-a.JPG" alt="KOSEN-1" /> <NuxtImg src="/images/kosen1_gunma-cgv5-a.JPG" alt="KOSEN-1" />
<p>画像菅原達弥(群馬高専)</p> <p>画像菅原達弥(群馬高専)</p>
</section> </section>
</main> </main>

View File

@@ -13,7 +13,7 @@ useSeoMeta(
<PankuzuList current-page-name="Rocket開発チーム" /> <PankuzuList current-page-name="Rocket開発チーム" />
<main> <main>
<section> <section>
<img <NuxtImg
src="/images/rocket_top.jpg" src="/images/rocket_top.jpg"
alt="Rocket top image" alt="Rocket top image"
class="float-left" class="float-left"
@@ -29,7 +29,7 @@ useSeoMeta(
<section> <section>
<h2>モデルロケットとは</h2> <h2>モデルロケットとは</h2>
<img <NuxtImg
src="/images/rocket/alpha3.jpg" src="/images/rocket/alpha3.jpg"
alt="Alpha III" alt="Alpha III"
class="float-right" class="float-right"
@@ -57,7 +57,7 @@ useSeoMeta(
<section> <section>
<h2>Rocket開発チームの活動</h2> <h2>Rocket開発チームの活動</h2>
<img <NuxtImg
src="/images/rocket/rocket_02.jpg" src="/images/rocket/rocket_02.jpg"
alt="2 staged rocket" alt="2 staged rocket"
class="float-left" class="float-left"