dummy content scaffolding
This commit is contained in:
parent
5c38cd9bdd
commit
750af00e08
9 changed files with 292 additions and 83 deletions
3
src/components.d.ts
vendored
3
src/components.d.ts
vendored
|
|
@ -18,10 +18,13 @@ declare module 'vue' {
|
||||||
Layout: typeof import('./components/Layout.vue')['default']
|
Layout: typeof import('./components/Layout.vue')['default']
|
||||||
Lenis: typeof import('./components/Lenis.vue')['default']
|
Lenis: typeof import('./components/Lenis.vue')['default']
|
||||||
LoadingSpinner: typeof import('./components/LoadingSpinner.vue')['default']
|
LoadingSpinner: typeof import('./components/LoadingSpinner.vue')['default']
|
||||||
|
MosaicModal: typeof import('./components/MosaicModal.vue')['default']
|
||||||
|
MosaicScroll: typeof import('./components/MosaicScroll.vue')['default']
|
||||||
MosaicViewport: typeof import('./components/MosaicViewport.vue')['default']
|
MosaicViewport: typeof import('./components/MosaicViewport.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
SiteHeader: typeof import('./components/site/Header.vue')['default']
|
SiteHeader: typeof import('./components/site/Header.vue')['default']
|
||||||
StrapiContent: typeof import('./components/strapi/Content.vue')['default']
|
StrapiContent: typeof import('./components/strapi/Content.vue')['default']
|
||||||
|
StrapiMedia: typeof import('./components/strapi/Media.vue')['default']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
</suspense>
|
</suspense>
|
||||||
|
|
||||||
<main class="main-content">
|
<main class="main-content">
|
||||||
<infinite-scroll-demo />
|
<mosaic-scroll :items="mosaicItems" />
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -13,9 +13,12 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useStrapiSingle } from '@/composables/useStrapi'
|
import { useStrapiSingle } from '@/composables/useStrapi'
|
||||||
import useStrapiHead from '@/composables/useStrapiHead'
|
import useStrapiHead from '@/composables/useStrapiHead'
|
||||||
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const { data } = await useStrapiSingle('home')
|
const { data } = await useStrapiSingle('home')
|
||||||
useStrapiHead()
|
useStrapiHead()
|
||||||
|
|
||||||
|
const mosaicItems = computed(() => data.value?.mosaic_items || [])
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
||||||
75
src/components/MosaicModal.vue
Normal file
75
src/components/MosaicModal.vue
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="mosaic-modal theme-dark layout-grid-inner"
|
||||||
|
@click="emit('close')"
|
||||||
|
>
|
||||||
|
<div class="window dl" @click.stop>
|
||||||
|
<dl-row v-for="row in item.dl" :row="row" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="window content" @click.stop data-lenis-prevent>
|
||||||
|
<h1 class="title">{{ item.title }}</h1>
|
||||||
|
<strapi-content :content="item.content" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="window close" @click="emit('close')">Close X</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps({ item: Object })
|
||||||
|
|
||||||
|
const emit = defineEmits(['close'])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.mosaic-modal {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding-top: desktop-vh(27px);
|
||||||
|
|
||||||
|
.window {
|
||||||
|
background: var(--theme-bg);
|
||||||
|
color: var(--theme-fg);
|
||||||
|
|
||||||
|
&.dl {
|
||||||
|
padding: desktop-vw(12px) desktop-vw(10px);
|
||||||
|
border-radius: desktop-vw(10px);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: desktop-vw(8px);
|
||||||
|
grid-column: 4 / span 2;
|
||||||
|
|
||||||
|
.dl-row:first-child {
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.content {
|
||||||
|
padding: desktop-vw(34px) desktop-vw(24px);
|
||||||
|
border-radius: desktop-vw(10px);
|
||||||
|
grid-column: 6 / span 7;
|
||||||
|
max-height: desktop-vh(879px);
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.close {
|
||||||
|
padding: desktop-vw(9px);
|
||||||
|
border-radius: desktop-vw(16px);
|
||||||
|
cursor: pointer;
|
||||||
|
/* position: absolute;
|
||||||
|
right: calc(
|
||||||
|
(var(--layout-column-width) * 3) +
|
||||||
|
(var(--layout-column-gap) * 3) + var(--layout-margin)
|
||||||
|
);
|
||||||
|
top: desktop-vw(40px); */
|
||||||
|
margin-right: auto;
|
||||||
|
@include label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="infinite-scroll-demo">
|
<div class="mosaic-scroll">
|
||||||
<infinite-scroll-container
|
<infinite-scroll-container
|
||||||
:bufferSize="2"
|
:bufferSize="2"
|
||||||
:initialIndex="0"
|
:initialIndex="0"
|
||||||
|
|
@ -21,20 +21,28 @@
|
||||||
import _shuffle from 'lodash/shuffle'
|
import _shuffle from 'lodash/shuffle'
|
||||||
import { useMosaicLayout } from '@/composables/useMosaicLayout'
|
import { useMosaicLayout } from '@/composables/useMosaicLayout'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
items: Array,
|
||||||
|
})
|
||||||
|
|
||||||
// Initialize mosaic layout generator
|
// Initialize mosaic layout generator
|
||||||
const { generateLayout, populateCells } = useMosaicLayout()
|
const { generateLayout, populateCells } = useMosaicLayout()
|
||||||
|
|
||||||
const generateGifContent = (cell) => {
|
// const generateGifContent = (cell) => {
|
||||||
return {
|
// return {
|
||||||
id: `gif-${cell.id}`,
|
// id: `gif-${cell.id}`,
|
||||||
width: Math.floor(cell.width),
|
// width: Math.floor(cell.width),
|
||||||
height: Math.floor(cell.height),
|
// height: Math.floor(cell.height),
|
||||||
note: _shuffle(
|
// note: _shuffle(
|
||||||
'curabitur euismod ultrices porttitor. Vivamus magna sapien, pretium at ullamcorper semper, sollicitudin et magna curabitur eget dolor a neque facilisis semper pellentesque euismod luctus urna, non aliquam justo aliquet id vestibulum quis lobortis diam nulla facilisi phasellus et rutrum lectus vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Praesent mattis felis condimentum, gravida lacus id, pretium neque. Donec cursus augue a dui placerat porttitor.Vestibulum rhoncus lectus nisl, nec gravida ex sollicitudin vel etiam dictum ac lacus ac elementum donec turpis eros, aliquam in nibh a, posuere tristique neque. Nunc cursus molestie consectetur.Integer placerat lorem eu nunc semper porta.'.split(
|
// 'curabitur euismod ultrices porttitor. Vivamus magna sapien, pretium at ullamcorper semper, sollicitudin et magna curabitur eget dolor a neque facilisis semper pellentesque euismod luctus urna, non aliquam justo aliquet id vestibulum quis lobortis diam nulla facilisi phasellus et rutrum lectus vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Praesent mattis felis condimentum, gravida lacus id, pretium neque. Donec cursus augue a dui placerat porttitor.Vestibulum rhoncus lectus nisl, nec gravida ex sollicitudin vel etiam dictum ac lacus ac elementum donec turpis eros, aliquam in nibh a, posuere tristique neque. Nunc cursus molestie consectetur.Integer placerat lorem eu nunc semper porta.'.split(
|
||||||
' ',
|
// ' ',
|
||||||
),
|
// ),
|
||||||
).join(' '),
|
// ).join(' '),
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
const generateCellContent = () => {
|
||||||
|
const itemIndex = Math.floor(Math.random() * props.items.length)
|
||||||
|
return props.items[itemIndex]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate mosaic content for each viewport
|
// Generate mosaic content for each viewport
|
||||||
|
|
@ -44,8 +52,6 @@ const generateMosaicContent = async (index) => {
|
||||||
const variance = Math.abs(index % 2) * 2
|
const variance = Math.abs(index % 2) * 2
|
||||||
const targetCells = baseCellCount + variance
|
const targetCells = baseCellCount + variance
|
||||||
|
|
||||||
// Generate layout with different parameters based on viewport index
|
|
||||||
// This adds variety to each viewport
|
|
||||||
const layoutOptions = {
|
const layoutOptions = {
|
||||||
minCellWidth: 200,
|
minCellWidth: 200,
|
||||||
minCellHeight: 200,
|
minCellHeight: 200,
|
||||||
|
|
@ -56,17 +62,16 @@ const generateMosaicContent = async (index) => {
|
||||||
const cells = generateLayout(layoutOptions)
|
const cells = generateLayout(layoutOptions)
|
||||||
|
|
||||||
// Populate cells with GIF content
|
// Populate cells with GIF content
|
||||||
const populatedCells = populateCells(cells, generateGifContent)
|
const populatedCells = populateCells(cells, generateCellContent)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
cells: populatedCells,
|
cells: populatedCells,
|
||||||
viewportIndex: index,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.infinite-scroll-demo {
|
.mosaic-scroll {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -3,7 +3,10 @@
|
||||||
<div class="mosaic-container">
|
<div class="mosaic-container">
|
||||||
<div
|
<div
|
||||||
v-for="cell in content.cells"
|
v-for="cell in content.cells"
|
||||||
class="mosaic-cell"
|
:class="[
|
||||||
|
'mosaic-cell',
|
||||||
|
`layout-${cell.width >= cell.height ? 'landscape' : 'portrait'}`,
|
||||||
|
]"
|
||||||
:style="{
|
:style="{
|
||||||
left: cell.x + 'px',
|
left: cell.x + 'px',
|
||||||
top: cell.y + 'px',
|
top: cell.y + 'px',
|
||||||
|
|
@ -11,38 +14,31 @@
|
||||||
height: cell.height + 'px',
|
height: cell.height + 'px',
|
||||||
}"
|
}"
|
||||||
:key="`${viewport.index}-${cell.id}`"
|
:key="`${viewport.index}-${cell.id}`"
|
||||||
@click="openNote(cell.content)"
|
@click="openModal(cell.content)"
|
||||||
>
|
>
|
||||||
<div class="gif-placeholder">
|
<strapi-media
|
||||||
<div class="gif-info">
|
:field="cell.content.image"
|
||||||
<span class="gif-id">{{ cell.content.id }}</span>
|
:aspect="100"
|
||||||
<span class="gif-size"
|
fit="contain"
|
||||||
>{{ Math.round(cell.width) }}x{{
|
/>
|
||||||
Math.round(cell.height)
|
|
||||||
}}</span
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Note modal -->
|
<!-- Content modal -->
|
||||||
<teleport to="#container">
|
<teleport to="#container">
|
||||||
<div v-if="selectedNote" class="note-modal-backdrop" @click="closeNote">
|
<mosaic-modal
|
||||||
<div class="note-modal" @click.stop>
|
v-if="selectedItem"
|
||||||
<button class="note-close" @click="closeNote">×</button>
|
:item="selectedItem"
|
||||||
<div class="note-content">
|
@close="closeModal"
|
||||||
<p>{{ selectedNote.note }}</p>
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</teleport>
|
</teleport>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { ref, watch } from 'vue'
|
||||||
import { useEventListener } from '@vueuse/core'
|
import { useEventListener } from '@vueuse/core'
|
||||||
import { ref } from 'vue'
|
import useLenis from '@/composables/useLenis'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
viewport: {
|
viewport: {
|
||||||
|
|
@ -63,26 +59,33 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const selectedNote = ref(null)
|
const selectedItem = ref(null)
|
||||||
|
|
||||||
const openNote = (cellContent) => {
|
const openModal = (cell) => {
|
||||||
if (cellContent.note) {
|
selectedItem.value = cell
|
||||||
selectedNote.value = cellContent
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const closeNote = () => {
|
const closeModal = () => {
|
||||||
selectedNote.value = null
|
selectedItem.value = null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close note on Escape key
|
// Close note on Escape key
|
||||||
const handleKeydown = (event) => {
|
const handleKeydown = (event) => {
|
||||||
if (event.key === 'Escape' && selectedNote.value) {
|
if (event.key === 'Escape' && selectedItem.value) {
|
||||||
closeNote()
|
closeModal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
useEventListener('keydown', handleKeydown)
|
useEventListener('keydown', handleKeydown)
|
||||||
|
|
||||||
|
// Pause scroll when modal is open
|
||||||
|
const lenis = useLenis()
|
||||||
|
watch(selectedItem, (newItem, oldItem) => {
|
||||||
|
if (newItem && !oldItem) {
|
||||||
|
lenis.value.stop()
|
||||||
|
} else if (oldItem && !newItem) {
|
||||||
|
lenis.value.start()
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
@ -101,37 +104,22 @@ useEventListener('keydown', handleKeydown)
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border: 1px solid var(--theme-fg);
|
border: 1px solid var(--theme-fg);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
.gif-placeholder {
|
&.layout-portrait {
|
||||||
height: 100%;
|
.strapi-media {
|
||||||
display: flex;
|
width: 50%;
|
||||||
align-items: center;
|
}
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
}
|
}
|
||||||
|
&.layout-landscape {
|
||||||
.gif-info {
|
.strapi-media {
|
||||||
display: flex;
|
height: 50%;
|
||||||
flex-direction: column;
|
aspect-ratio: 1;
|
||||||
align-items: center;
|
}
|
||||||
gap: 0.25rem;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-modal-backdrop {
|
|
||||||
position: fixed;
|
|
||||||
inset: 0;
|
|
||||||
background: rgba(0, 0, 0, 0.5);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.note-modal {
|
|
||||||
background: var(--theme-bg);
|
|
||||||
width: 50vw;
|
|
||||||
padding: 2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<header v-if="data" class="site-header">
|
<header v-if="data" class="site-header layout-grid-inner">
|
||||||
<img class="logo" src="/images/output_pixelated.gif" />
|
<img class="logo" src="/images/output_pixelated.gif" />
|
||||||
|
|
||||||
<div class="info theme-red">
|
<div class="info theme-red">
|
||||||
|
|
@ -24,7 +24,6 @@ const { data } = await useStrapiGlobal()
|
||||||
right: 0;
|
right: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
padding: desktop-vw(27px);
|
padding: desktop-vw(27px);
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
|
||||||
> * {
|
> * {
|
||||||
|
|
@ -39,9 +38,9 @@ const { data } = await useStrapiGlobal()
|
||||||
.info {
|
.info {
|
||||||
background: var(--theme-bg);
|
background: var(--theme-bg);
|
||||||
color: var(--theme-fg);
|
color: var(--theme-fg);
|
||||||
width: desktop-vw(173px);
|
|
||||||
border-radius: desktop-vw(10px);
|
border-radius: desktop-vw(10px);
|
||||||
padding: desktop-vw(12px) desktop-vw(10px);
|
padding: desktop-vw(12px) desktop-vw(10px);
|
||||||
|
grid-column: 2 / span 2;
|
||||||
|
|
||||||
.copy {
|
.copy {
|
||||||
margin-bottom: desktop-vw(18px);
|
margin-bottom: desktop-vw(18px);
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,11 @@ const props = defineProps({
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.strapi-content {
|
.strapi-content {
|
||||||
|
> * {
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
> *:first-child {
|
> *:first-child {
|
||||||
margin-top: 0 !important;
|
margin-top: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
131
src/components/strapi/Media.vue
Normal file
131
src/components/strapi/Media.vue
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-if="image"
|
||||||
|
:class="['strapi-media', { 'fill-space': fillSpace }, `fit-${fit}`]"
|
||||||
|
:style="styles"
|
||||||
|
>
|
||||||
|
<div class="image-sizer">
|
||||||
|
<img
|
||||||
|
:src="addURLBase(image.url)"
|
||||||
|
:srcset="srcset"
|
||||||
|
:sizes="sizes"
|
||||||
|
:alt="image.alternativeText || ''"
|
||||||
|
:width="image.width"
|
||||||
|
:height="image.height"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { breakpoints } from '@/libs/theme'
|
||||||
|
import { computed } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
field: Object,
|
||||||
|
aspect: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: () => -1,
|
||||||
|
},
|
||||||
|
fillSpace: {
|
||||||
|
type: Boolean,
|
||||||
|
default: () => false,
|
||||||
|
},
|
||||||
|
fit: {
|
||||||
|
type: String,
|
||||||
|
default: () => 'cover',
|
||||||
|
},
|
||||||
|
mobileSize: {
|
||||||
|
type: String,
|
||||||
|
default: () => '100vw',
|
||||||
|
},
|
||||||
|
desktopSize: {
|
||||||
|
type: String,
|
||||||
|
default: () => '100vw',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const addURLBase = (path) => `https://cms.nicwands.com${path}`
|
||||||
|
|
||||||
|
// const image = computed(() => props.field.image)
|
||||||
|
const image = computed(() => props.field)
|
||||||
|
const formats = computed(() => image.value?.formats || {})
|
||||||
|
const ratio = computed(() => {
|
||||||
|
if (!image.value) return 1
|
||||||
|
return image.value.height / image.value.width
|
||||||
|
})
|
||||||
|
const aspect = computed(() => {
|
||||||
|
// calculate if no aspect provided
|
||||||
|
if (props.aspect === -1) {
|
||||||
|
return ratio.value * 100
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise, parse provided aspect, handling both 56.25 and 0.5625 style
|
||||||
|
const toParse = parseFloat(props.aspect)
|
||||||
|
return toParse <= 1 ? toParse * 100 : toParse
|
||||||
|
})
|
||||||
|
const styles = computed(() => ({ '--aspect': aspect.value + '%' }))
|
||||||
|
const srcset = computed(() =>
|
||||||
|
Object.values(formats.value)
|
||||||
|
.map((f) => `${addURLBase(f.url)} ${f.width}w`)
|
||||||
|
.join(', '),
|
||||||
|
)
|
||||||
|
const sizes = computed(
|
||||||
|
() =>
|
||||||
|
`(max-width: ${breakpoints.mobile}) ${props.mobileSize}, ${props.desktopSize}`,
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.strapi-media {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.image-sizer {
|
||||||
|
overflow: hidden;
|
||||||
|
padding-bottom: var(--aspect);
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
.svg {
|
||||||
|
background-size: cover;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill space
|
||||||
|
&.fill-space {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
|
||||||
|
.image-sizer {
|
||||||
|
padding-bottom: 0;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fits
|
||||||
|
&.fit-cover .image-sizer > * {
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
&.fit-contain .image-sizer > * {
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -21,15 +21,15 @@
|
||||||
$layout: (
|
$layout: (
|
||||||
'columns-count': (
|
'columns-count': (
|
||||||
5,
|
5,
|
||||||
18,
|
15,
|
||||||
),
|
),
|
||||||
'columns-gap': (
|
'columns-gap': (
|
||||||
20px,
|
20px,
|
||||||
20px,
|
20px,
|
||||||
),
|
),
|
||||||
'margin': (
|
'margin': (
|
||||||
30px,
|
20px,
|
||||||
60px,
|
20px,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue