Applied NuxtImg to pages and components
This commit is contained in:
@@ -1,111 +1,133 @@
|
||||
<script setup lang="ts">
|
||||
import type { LinkCardProperty } from "~/utils/types/linkCard";
|
||||
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>
|
||||
|
||||
<template>
|
||||
<NuxtLink :to="property.link" :class="{ withoutImage: doesNotHaveImage }">
|
||||
<div
|
||||
class="image"
|
||||
v-if="property.imagePath"
|
||||
:style="{ backgroundImage: `url(${property.imagePath})` }"
|
||||
></div>
|
||||
<h2>{{ property.title }}</h2>
|
||||
<p>{{ property.description }}</p>
|
||||
</NuxtLink>
|
||||
<div class="card-wrapper">
|
||||
<NuxtLink :to="property.link" class="card">
|
||||
<div class="image">
|
||||
<div :style="optimizeImage(imagePath)"></div>
|
||||
</div>
|
||||
<div class="texts">
|
||||
<h2>{{ property.title }}</h2>
|
||||
<p>{{ property.description }}</p>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<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;
|
||||
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;
|
||||
color: var(--neptune1);
|
||||
background-color: var(--starlight5);
|
||||
grid-template-areas: "image texts";
|
||||
border-radius: 1rem;
|
||||
margin: 0.75rem 2rem;
|
||||
padding: 1rem 1.75rem;
|
||||
align-self: center;
|
||||
line-height: 2rem;
|
||||
font-size: clamp(16pt, 3vw, 20pt);
|
||||
}
|
||||
|
||||
h2::after {
|
||||
display: block;
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 7px;
|
||||
height: max(2rem, 60%);
|
||||
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;
|
||||
box-shadow: 10px 5px 5px var(--starlight1);
|
||||
background-color: var(--starlight);
|
||||
min-width: calc(var(--minimum-card-width) - 2 * var(--card-padding-inline));
|
||||
min-height: calc(
|
||||
var(--minimum-card-height) - 2 * var(--card-padding-vertical)
|
||||
);
|
||||
padding: var(--card-padding-vertical) var(--card-padding-inline);
|
||||
transition: all 0.3s ease-in-out;
|
||||
text-decoration: none;
|
||||
aspect-ratio: 5 / 2;
|
||||
&:hover {
|
||||
scale: 105%;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 640px) {
|
||||
a {
|
||||
width: 16rem;
|
||||
.card > .image {
|
||||
grid-area: image;
|
||||
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 {
|
||||
width: 12rem;
|
||||
height: 8rem;
|
||||
margin-top: 0.75rem;
|
||||
& > p {
|
||||
color: var(--deep-space);
|
||||
height: 25cqw;
|
||||
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>
|
||||
|
||||
@@ -1,9 +1,24 @@
|
||||
<script setup lang="ts">
|
||||
import type { NewsCardProperty } from "~/utils/types/newsCard";
|
||||
import DOMPurify from "isomorphic-dompurify";
|
||||
import { marked } from "marked";
|
||||
|
||||
const { backgroundImageStyles } = useBackgroundImageOptimization();
|
||||
const optimizeImage = (backgroundImagePath: string) => {
|
||||
backgroundImageStyles.value = backgroundImagePath;
|
||||
return backgroundImageStyles.value;
|
||||
};
|
||||
|
||||
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(
|
||||
property.newsEntry.date as number
|
||||
).toLocaleDateString("ja-JP", { dateStyle: "medium" });
|
||||
@@ -16,41 +31,32 @@ const coverImagePath = ref<string>(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="news-card"
|
||||
:style="{ backgroundImage: `url(${coverImagePath})` }"
|
||||
>
|
||||
<div class="news-card" :style="optimizeImage(coverImagePath)">
|
||||
<NuxtLink
|
||||
class="card-content"
|
||||
:to="property.newsEntry.linkPath"
|
||||
v-if="
|
||||
property.newsEntry.linkPath !== null &&
|
||||
property.newsEntry.entryType === EntryType.Article
|
||||
"
|
||||
v-bind:data-type="property.newsEntry.entryType"
|
||||
:to="property.newsEntry.linkPath || ''"
|
||||
>
|
||||
<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>
|
||||
<div class="content">
|
||||
<article
|
||||
v-html="
|
||||
marked.parse(property.newsEntry.cardContent as string)
|
||||
DOMPurify.sanitize(
|
||||
marked.parse(
|
||||
property.newsEntry.cardContent as string
|
||||
) as string
|
||||
)
|
||||
"
|
||||
></article>
|
||||
</div>
|
||||
<small>{{ datePosted }}</small>
|
||||
</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>
|
||||
</template>
|
||||
|
||||
@@ -66,6 +72,12 @@ const coverImagePath = ref<string>(
|
||||
background-position: center;
|
||||
background-attachment: local;
|
||||
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 {
|
||||
@@ -78,36 +90,31 @@ const coverImagePath = ref<string>(
|
||||
right: 0;
|
||||
width: 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%);
|
||||
color: var(--starlight);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.card-content .content {
|
||||
.card-content > .content {
|
||||
font-size: larger;
|
||||
font-weight: 400;
|
||||
margin-top: 2.75rem;
|
||||
}
|
||||
|
||||
.card-content article,
|
||||
.card-content img {
|
||||
.content > article {
|
||||
margin: 0 1rem;
|
||||
}
|
||||
|
||||
.card-content img {
|
||||
margin-top: 3rem;
|
||||
width: 10rem;
|
||||
height: auto;
|
||||
padding: 0.25rem;
|
||||
margin-left: 1.75rem;
|
||||
.content > article :deep(a) {
|
||||
font-weight: 600;
|
||||
color: var(--neptune2);
|
||||
&:visited {
|
||||
color: var(--neptune2);
|
||||
}
|
||||
}
|
||||
|
||||
.card-content img[src="/sera-logo-text.svg"] {
|
||||
background-color: var(--starlight);
|
||||
}
|
||||
|
||||
.card-content .news-type {
|
||||
.card-content > .news-type {
|
||||
position: absolute;
|
||||
margin: 0;
|
||||
padding-top: 0.25rem;
|
||||
@@ -119,17 +126,17 @@ const coverImagePath = ref<string>(
|
||||
border-bottom-right-radius: 1rem;
|
||||
}
|
||||
|
||||
.card-content .tweet {
|
||||
.card-content > .tweet {
|
||||
background-color: var(--venus2);
|
||||
color: var(--venus1);
|
||||
}
|
||||
|
||||
.card-content .article {
|
||||
.card-content > .article {
|
||||
background-color: var(--venus1);
|
||||
color: var(--astronaut);
|
||||
}
|
||||
|
||||
.card-content .new {
|
||||
.card-content > .new {
|
||||
position: absolute;
|
||||
margin: 0;
|
||||
right: 0;
|
||||
@@ -144,7 +151,7 @@ const coverImagePath = ref<string>(
|
||||
border-bottom-left-radius: 1rem;
|
||||
}
|
||||
|
||||
.card-content small {
|
||||
.card-content > small {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
import type { PageTopProperty } from "~/utils/types/pageTop";
|
||||
|
||||
const property = defineProps<PageTopProperty>();
|
||||
const backgroundImageOptimizer = useBackgroundImageOptimization();
|
||||
|
||||
backgroundImageOptimizer.backgroundImageStyles.value = property.imagePath;
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :style="{ backgroundImage: `url(${property.imagePath})` }">
|
||||
<div :style="backgroundImageOptimizer.backgroundImageStyles.value">
|
||||
{{ property.text }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
<script setup lang="ts">
|
||||
import type { SlideProperty, SlideEntry } from "~/utils/types/slide.ts";
|
||||
|
||||
import DOMPurify from "isomorphic-dompurify";
|
||||
import { marked } from "marked";
|
||||
|
||||
const property = defineProps<SlideProperty>();
|
||||
const { viewPortOrientation } = useWindowDimensions();
|
||||
const { backgroundImageStyles } = useBackgroundImageOptimization();
|
||||
|
||||
const optimizeImage = (backgroundImagePath: string) => {
|
||||
backgroundImageStyles.value = backgroundImagePath;
|
||||
return backgroundImageStyles.value;
|
||||
};
|
||||
|
||||
const UnitREM = 16;
|
||||
const fourREM = 4 * UnitREM;
|
||||
@@ -169,15 +177,20 @@ onUnmounted(() => {
|
||||
<li
|
||||
v-for="(entry, index) in property.entries"
|
||||
:key="index"
|
||||
:style="{
|
||||
backgroundImage: `url('${entry.imagePath}')`,
|
||||
}"
|
||||
:style="optimizeImage(entry.imagePath)"
|
||||
v-show="currentSlide === index"
|
||||
class="slide"
|
||||
>
|
||||
<div class="content">
|
||||
<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>
|
||||
@@ -192,7 +205,7 @@ onUnmounted(() => {
|
||||
class="preview"
|
||||
@click="handelClick(entry)"
|
||||
>
|
||||
<img :src="entry.imagePath" alt="slide image preview" />
|
||||
<NuxtImg :src="entry.imagePath" alt="slide image preview" />
|
||||
<svg
|
||||
width="72"
|
||||
height="72"
|
||||
@@ -257,14 +270,25 @@ ul {
|
||||
text-align: center;
|
||||
color: var(--starlight);
|
||||
}
|
||||
& > p {
|
||||
& > :deep(.rendered-paragraph) p {
|
||||
height: 3rem;
|
||||
margin: 0;
|
||||
justify-self: center;
|
||||
color: var(--starlight);
|
||||
font-size: clamp(14pt, 1.5cqw, 24pt);
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
}
|
||||
& > :deep(.rendered-paragraph) a {
|
||||
color: var(--neptune2);
|
||||
&:visited {
|
||||
color: var(--neptune2);
|
||||
}
|
||||
}
|
||||
& > .rendered-paragraph {
|
||||
height: 3rem;
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
& > a {
|
||||
width: fit-content;
|
||||
border: var(--starlight) 3px solid;
|
||||
@@ -375,9 +399,4 @@ ul {
|
||||
margin: calc(1rem / 16) 0;
|
||||
}
|
||||
}
|
||||
|
||||
.portrait-controler {
|
||||
flex-direction: column;
|
||||
right: 0rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
30
composables/backgroundImageOptimization.ts
Normal file
30
composables/backgroundImageOptimization.ts
Normal 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 };
|
||||
@@ -28,7 +28,7 @@ useSeoMeta(
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<img
|
||||
<NuxtImg
|
||||
src="/images/koshien2020_mission-rogo.png"
|
||||
alt="2020 Mission Logo"
|
||||
class="float-right"
|
||||
@@ -58,7 +58,7 @@ useSeoMeta(
|
||||
<section>
|
||||
<h3>種子島ロケットコンテスト</h3>
|
||||
<h4>滑空・定点回収</h4>
|
||||
<img
|
||||
<NuxtImg
|
||||
src="/images/rocket_top.jpg"
|
||||
alt="rockets"
|
||||
class="float-right"
|
||||
@@ -93,7 +93,7 @@ useSeoMeta(
|
||||
</ul>
|
||||
<br />
|
||||
<h4>CanSat</h4>
|
||||
<img
|
||||
<NuxtImg
|
||||
src="/images/cansat/cansat_03.jpg"
|
||||
alt="Sample Image"
|
||||
class="float-right"
|
||||
@@ -145,7 +145,7 @@ useSeoMeta(
|
||||
|
||||
<section>
|
||||
<h2>その他活動実績 (イベントなど)</h2>
|
||||
<img
|
||||
<NuxtImg
|
||||
src="/images/uchu_fea.jpg"
|
||||
alt="Sample Image"
|
||||
class="float-right"
|
||||
|
||||
@@ -63,7 +63,7 @@ useSeoMeta(
|
||||
:key="entry.id"
|
||||
>
|
||||
<figure>
|
||||
<img :src="entry.imagePath" :alt="entry.caption" />
|
||||
<NuxtImg :src="entry.imagePath" :alt="entry.caption" />
|
||||
<figcaption>{{ entry.caption }}</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
@@ -73,7 +73,7 @@ useSeoMeta(
|
||||
<button @click="closeViewer" class="close">
|
||||
<Icon name="ic:baseline-close" />
|
||||
</button>
|
||||
<img :src="imagePathViewer" :alt="captionViewer" />
|
||||
<NuxtImg :src="imagePathViewer" :alt="captionViewer" />
|
||||
<p>{{ captionViewer }}</p>
|
||||
<button @click="changeImage(Direction.FORWARD)" class="next">
|
||||
<Icon name="material-symbols:arrow-forward-rounded" />
|
||||
@@ -163,6 +163,7 @@ main {
|
||||
grid-area: caption;
|
||||
justify-self: center;
|
||||
align-self: flex-end;
|
||||
margin-inline: 1.25rem;
|
||||
}
|
||||
|
||||
.image-viewer .close {
|
||||
|
||||
@@ -15,7 +15,11 @@ useSeoMeta(
|
||||
<PankuzuList current-page-name="SERAについて" />
|
||||
<main>
|
||||
<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>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import DOMPurify from "isomorphic-dompurify";
|
||||
import { marked } from "marked";
|
||||
|
||||
const route = useRoute();
|
||||
@@ -30,9 +31,10 @@ onMounted(() => {
|
||||
postedDateElement.textContent = "掲載日: " + postedDate;
|
||||
articleTitle?.insertAdjacentElement("afterend", postedDateElement);
|
||||
const cardContentConversion = document.createElement("div");
|
||||
cardContentConversion.innerHTML = marked.parse(
|
||||
data.value?.cardContent as string
|
||||
) as string;
|
||||
const purifiedHTML = DOMPurify.sanitize(
|
||||
marked.parse(data.value?.cardContent as string) as string
|
||||
);
|
||||
cardContentConversion.innerHTML = purifiedHTML;
|
||||
useSeoMeta(
|
||||
generateSeoMeta(
|
||||
articleTitle?.innerText as string,
|
||||
@@ -48,11 +50,17 @@ onMounted(() => {
|
||||
<PageTop text="News" image-path="/images/news-top.jpg" />
|
||||
<PankuzuList :current-page-name="pankuzuListPageName()" />
|
||||
<main>
|
||||
<img :src="(data?.coverImagePath as string) || '/sera-logo-text.svg'" />
|
||||
<NuxtImg
|
||||
:src="(data?.coverImagePath as string) || '/sera-logo-text.svg'"
|
||||
/>
|
||||
<div
|
||||
id="article"
|
||||
class="markdown"
|
||||
v-html="marked.parse(data?.article as string)"
|
||||
v-html="
|
||||
DOMPurify.sanitize(
|
||||
marked.parse(data?.article as string) as string
|
||||
)
|
||||
"
|
||||
></div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
@@ -13,7 +13,7 @@ useSeoMeta(
|
||||
<PankuzuList current-page-name="CanSat開発チーム" />
|
||||
<main>
|
||||
<section>
|
||||
<img
|
||||
<NuxtImg
|
||||
src="/images/cansat_top.jpg"
|
||||
alt="CanSat top image"
|
||||
class="float-left"
|
||||
@@ -29,7 +29,7 @@ useSeoMeta(
|
||||
|
||||
<section>
|
||||
<h2>CanSatとは</h2>
|
||||
<img
|
||||
<NuxtImg
|
||||
src="/images/cansat/cansat_01.jpg"
|
||||
alt="CanSat"
|
||||
class="float-right"
|
||||
@@ -52,7 +52,7 @@ useSeoMeta(
|
||||
|
||||
<section>
|
||||
<h2>CanSat開発チームの活動</h2>
|
||||
<img
|
||||
<NuxtImg
|
||||
src="/images/cansat/cansat_02.jpg"
|
||||
alt="SERA自作ロケット"
|
||||
class="float-left"
|
||||
@@ -74,7 +74,7 @@ useSeoMeta(
|
||||
|
||||
<section>
|
||||
<h3>缶サット甲子園</h3>
|
||||
<img
|
||||
<NuxtImg
|
||||
src="/images/cansat/koshien2020.jpg"
|
||||
alt="缶サット甲子園"
|
||||
class="float-right"
|
||||
@@ -92,7 +92,7 @@ useSeoMeta(
|
||||
|
||||
<section>
|
||||
<h3>種子島ロケットコンテスト</h3>
|
||||
<img
|
||||
<NuxtImg
|
||||
src="/images/cansat/seratank-1.png"
|
||||
alt="SERATANK-1"
|
||||
class="float-left"
|
||||
|
||||
@@ -30,7 +30,7 @@ useSeoMeta(
|
||||
|
||||
<section>
|
||||
<h3>AlphaⅢ</h3>
|
||||
<img
|
||||
<NuxtImg
|
||||
src="/images/rocket/alpha3.jpg"
|
||||
alt="Alpha III"
|
||||
class="float-left"
|
||||
@@ -44,7 +44,7 @@ useSeoMeta(
|
||||
|
||||
<section>
|
||||
<h3>Raspberry Pi</h3>
|
||||
<img
|
||||
<NuxtImg
|
||||
src="/images/education/raspberry-pi-4.jpg"
|
||||
alt="Raspberry Pi 4"
|
||||
class="float-right"
|
||||
@@ -79,7 +79,7 @@ useSeoMeta(
|
||||
|
||||
<section>
|
||||
<h2>教育用ローバーの開発</h2>
|
||||
<img
|
||||
<NuxtImg
|
||||
src="/images/education/education-1.jpg"
|
||||
alt="教育用ローバー"
|
||||
class="float-left"
|
||||
|
||||
@@ -68,7 +68,7 @@ useSeoMeta(
|
||||
</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>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
@@ -13,7 +13,7 @@ useSeoMeta(
|
||||
<PankuzuList current-page-name="Rocket開発チーム" />
|
||||
<main>
|
||||
<section>
|
||||
<img
|
||||
<NuxtImg
|
||||
src="/images/rocket_top.jpg"
|
||||
alt="Rocket top image"
|
||||
class="float-left"
|
||||
@@ -29,7 +29,7 @@ useSeoMeta(
|
||||
|
||||
<section>
|
||||
<h2>モデルロケットとは</h2>
|
||||
<img
|
||||
<NuxtImg
|
||||
src="/images/rocket/alpha3.jpg"
|
||||
alt="Alpha III"
|
||||
class="float-right"
|
||||
@@ -57,7 +57,7 @@ useSeoMeta(
|
||||
|
||||
<section>
|
||||
<h2>Rocket開発チームの活動</h2>
|
||||
<img
|
||||
<NuxtImg
|
||||
src="/images/rocket/rocket_02.jpg"
|
||||
alt="2 staged rocket"
|
||||
class="float-left"
|
||||
|
||||
Reference in New Issue
Block a user