Skip to content

Instantly share code, notes, and snippets.

@GeN-w-DeJA
Last active July 5, 2020 19:16
Show Gist options
  • Save GeN-w-DeJA/212a73ff9948c12f540732cdb598242f to your computer and use it in GitHub Desktop.
Save GeN-w-DeJA/212a73ff9948c12f540732cdb598242f to your computer and use it in GitHub Desktop.
GenXsgallery
//- PREVIOUS VERSION: https://codepen.io/mican/pen/awxmpY
- var placeholder = function(width, height) { return "data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http://www.w3.org/2000/svg'%20viewBox%3D'0%200%20" + width + "%20" + height + "'%20%2F%3E" }
- var images = [{ id: '-gS54SWrHMg', width: 1000, height: 500 },{id: 'AU1rKyKPJco', width: 500, height: 1000, caption: 'Hello from Poland' },{ id: 'AXfDvKOawZQ' },{ id: 'gKlkZrsG_Pw', width: 1000, height: 500 },{ id: 'DVONaLgCRxo', width: 500, height: 1000 },{ id: 'o7txpYpxNLs', caption: 'Have a nice day' },{ id: 'ZsgUsl8GATg', width: 500, height: 1000, caption: 'This is a very very long description to show you it\'s possible to add something like this' },{ id: 'CkagyZJ88kE' },{ id: 'PpQ4-HOZ_8U', width: 1000, height: 500 },{ id: 'si7gjqJQj_8' },{ id: 'u0M0gyuexfE', width: 500, height: 1000 },{ id: 'aQcE3gDSSTY' },{ id: 'GkCafprWKRo', width: 500, height: 1000 },{ id: 'OFlzoTfpRdw' },{ id: 'YlFM0-LdHu8' },{ id: 'c_Tc9ZELeYw' }]
mixin gallery-item(id, width=500, height=500, caption)
if height > width
- var klass = 'vertical'
else if width > height
- var klass = 'horizontal'
figure.gallery-item(itemprop='associatedMedia', itemscope='', itemtype='http://schema.org/ImageObject', class=klass)
a(href=`https://source.unsplash.com/${id}/${width*2}x${height*2}`, itemprop='contentUrl', data-size=`${width*2}x${height*2}`)
img.lazyload.lazypreload.fadein(src=placeholder(width,height) data-src=`https://source.unsplash.com/${id}/${width}x${height}`, itemprop='thumbnail', alt='Image description')
figcaption.gallery-caption(itemprop='caption description')= caption || 'Caption'
.gallery(itemscope='', itemtype='http://schema.org/ImageGallery')
each image in images
+gallery-item(image.id,image.width,image.height, image.caption)
// Root element of PhotoSwipe. Must have class pswp.
.pswp(tabindex='-1', role='dialog', aria-hidden='true')
//
Background of PhotoSwipe.
It's a separate element as animating opacity is faster than rgba().
.pswp__bg
// Slides wrapper with overflow:hidden.
.pswp__scroll-wrap
//
Container that holds slides.
PhotoSwipe keeps only 3 of them in the DOM to save memory.
Don't modify these 3 pswp__item elements, data is added later on.
.pswp__container
.pswp__item
.pswp__item
.pswp__item
// Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed.
.pswp__ui.pswp__ui--hidden
.pswp__top-bar
// Controls are self-explanatory. Order can be changed.
.pswp__counter
button.pswp__button.pswp__button--close(title='Close (Esc)')
button.pswp__button.pswp__button--share(title='Share')
button.pswp__button.pswp__button--fs(title='Toggle fullscreen')
button.pswp__button.pswp__button--zoom(title='Zoom in/out')
// Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR
// element will get class pswp__preloader--active when preloader is running
.pswp__preloader
.pswp__preloader__icn
.pswp__preloader__cut
.pswp__preloader__donut
.pswp__share-modal.pswp__share-modal--hidden.pswp__single-tap
.pswp__share-tooltip
button.pswp__button.pswp__button--arrow--left(title='Previous (arrow left)')
button.pswp__button.pswp__button--arrow--right(title='Next (arrow right)')
.pswp__caption
.pswp__caption__center
initPhotoSwipeFromDOM = (gallerySelector) ->
# parse slide data (url, title, size ...) from DOM elements
# (children of gallerySelector)
parseThumbnailElements = (el) ->
thumbElements = el.childNodes
numNodes = thumbElements.length
items = []
figureEl = undefinedinitPhotoSwipeFromDOM = (gallerySelector) ->
# parse slide data (url, title, size ...) from DOM elements
# (children of gallerySelector)
parseThumbnailElements = (el) ->
thumbElements = el.childNodes
numNodes = thumbElements.length
items = []
figureEl = undefined
linkEl = undefined
size = undefined
item = undefined
i = 0
while i < numNodes
figureEl = thumbElements[i]
# <figure> element
# include only element nodes
if figureEl.nodeType != 1
i++
linkEl = undefined
size = undefined
item = undefined
i = 0
while i < numNodes
figureEl = thumbElements[i]
# <figure> element
# include only element nodes
if figureEl.nodeType != 1
i++
continue
linkEl = figureEl.children[0]
# <a> element
size = linkEl.getAttribute('data-size').split('x')
# create slide object
item =
src: linkEl.getAttribute('href')
w: parseInt(size[0], 10)
h: parseInt(size[1], 10)
if figureEl.children.length > 1
# <figcaption> content
item.title = figureEl.children[1].innerHTML
if linkEl.children.length > 0
# <img> thumbnail element, retrieving thumbnail url
item.msrc = linkEl.children[0].getAttribute('src')
item.el = figureEl
# save link to element for getThumbBoundsFn
items.push item
i++
items
# find nearest parent element
closest = (el, fn) ->
el and (if fn(el) then el else closest(el.parentNode, fn))
# triggers when user clicks on thumbnail
onThumbnailsClick = (e) ->
e = e or window.event
if e.preventDefault then e.preventDefault() else (e.returnValue = false)
eTarget = e.target or e.srcElement
# find root element of slide
clickedListItem = closest(eTarget, (el) ->
el.tagName and el.tagName.toUpperCase() == 'FIGURE'
)
if !clickedListItem
return
# find index of clicked item by looping through all child nodes
# alternatively, you may define index via data- attribute
clickedGallery = clickedListItem.parentNode
childNodes = clickedListItem.parentNode.childNodes
numChildNodes = childNodes.length
nodeIndex = 0
index = undefined
i = 0
while i < numChildNodes
if childNodes[i].nodeType != 1
i++
continue
if childNodes[i] == clickedListItem
index = nodeIndex
break
nodeIndex++
i++
if index >= 0
# open PhotoSwipe if valid index found
openPhotoSwipe index, clickedGallery
false
# parse picture index and gallery index from URL (#&pid=1&gid=2)
photoswipeParseHash = ->
hash = window.location.hash.substring(1)
params = {}
if hash.length < 5
return params
vars = hash.split('&')
i = 0
while i < vars.length
if !vars[i]
i++
continue
pair = vars[i].split('=')
if pair.length < 2
i++
continue
params[pair[0]] = pair[1]
i++
if params.gid
params.gid = parseInt(params.gid, 10)
params
openPhotoSwipe = (index, galleryElement, disableAnimation, fromURL) ->
pswpElement = document.querySelectorAll('.pswp')[0]
gallery = undefined
options = undefined
items = undefined
items = parseThumbnailElements(galleryElement)
# define options (if needed)
options =
galleryUID: galleryElement.getAttribute('data-pswp-uid')
getThumbBoundsFn: (index) ->
# See Options -> getThumbBoundsFn section of documentation for more info
thumbnail = items[index].el.getElementsByTagName('img')[0]
pageYScroll = window.pageYOffset or document.documentElement.scrollTop
rect = thumbnail.getBoundingClientRect()
{
x: rect.left
y: rect.top + pageYScroll
w: rect.width
}
# PhotoSwipe opened from URL
if fromURL
if options.galleryPIDs
# parse real index when custom PIDs are used
# http://photoswipe.com/documentation/faq.html#custom-pid-in-url
j = 0
while j < items.length
if items[j].pid == index
options.index = j
break
j++
else
# in URL indexes start from 1
options.index = parseInt(index, 10) - 1
else
options.index = parseInt(index, 10)
# exit if index not found
if isNaN(options.index)
return
if disableAnimation
options.showAnimationDuration = 0
# Pass data to PhotoSwipe and initialize it
gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, options)
gallery.init()
return
# loop through all gallery elements and bind events
galleryElements = document.querySelectorAll(gallerySelector)
i = 0
l = galleryElements.length
while i < l
galleryElements[i].setAttribute 'data-pswp-uid', i + 1
galleryElements[i].onclick = onThumbnailsClick
i++
# Parse URL and open gallery if it contains #&pid=3&gid=1
hashData = photoswipeParseHash()
if hashData.pid and hashData.gid
openPhotoSwipe hashData.pid, galleryElements[hashData.gid - 1], true, true
return
# execute above function
initPhotoSwipeFromDOM '.gallery'
# ---
# generated by js2coffee 2.2.0
<script src="https://cdnjs.cloudflare.com/ajax/libs/lazysizes/4.0.2/lazysizes.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.2/photoswipe.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.2/photoswipe-ui-default.js"></script>
%gallery-caption
+absolute(bottom 4rem left 50%)
transform: translate(-50%,0%)
font-size: 12px
+breakpoint($mobile)
font-size: 14px
color: rgba(white,0)
padding: 1.25em 1.5em
transition: all .2s ease
font-weight: 600
// min-width: 10rem
// width: 50%
// max-width: calc(100% - 6rem)
line-height: 1.25
text-align: center
box-sizing: border-box
pointer-events: none
&:before, &:after
content: ''
+absolute(top right left bottom)
background: rgba(black,1)
width: 100%
height: 100%
transition: all .3s ease 0s
z-index: -1
&:before
top: auto
height: 3px
transform: scale(0,1)
transform-origin: bottom left
transition-delay: .6s
&:after
transform: scale(1,0)
transform-origin: bottom
transition-delay: .3s
&.visible
color: rgba(white,1)
text-shadow: 0 0 1px rgba(black,.2)
transition: all .3s ease .3s
&:before
transform: scale(1,1)
transition-delay: 0s
&:after
transform: scale(1,1)
&:empty
display: none
$corner: 1rem
%image-border
+relative
&:before, &:after
content: ''
+absolute(top right left bottom)
border: 0 solid rgba(black,.1)
transition: all .2s
will-change: border
z-index: 10
&.active
&:before
border-width: .5rem
&:after
border-width: 2px
&:after
margin: $corner
border: 2px solid rgba(white,.5)
clip-path: polygon(0 calc(100% - #{$corner}), 0 100%, $corner 100%, $corner 0, 0 0, 0 $corner, 100% $corner, 100% 0, calc(100% - #{$corner}) 0, calc(100% - #{$corner}) 100%, 100% 100%, 100% calc(100% - #{$corner}))
&:hover
&:after
transform: scale(.9)
border-color: rgba(white,1)
%caption-outside
background-color: black
color: white
padding: .75em 1em
display: inline-block
text-align: left
%gallery-grid
+sans-serif-font
width: 100%
display: grid
grid-template-rows: flow
grid-auto-flow: dense
+breakpoint(max-width $mobile - 1px)
grid-template-columns: repeat(2, 1fr)
+breakpoint($mobile $desktop - 1px)
grid-template-columns: repeat(3, 1fr)
+breakpoint($desktop $laptop - px)
grid-template-columns: repeat(4, 1fr)
+breakpoint($laptop $screen - 1px)
grid-template-columns: repeat(5, 1fr)
+breakpoint($screen)
grid-template-columns: repeat(6, 1fr)
%gallery-item
+relative
background-color: rgba(black,.5)
overflow: hidden
img, a
display: block
&.vertical
grid-row: span 2
&.horizontal
grid-column: span 2
.gallery
@extend %gallery-grid
.gallery-item
@extend %gallery-item
a
display: block
@extend %image-border
.lazy-images &.image-lazyloaded, html:not(.lazy-images) &
@extend %image-border.active
.gallery-caption
html:not(.touchevents) &
@extend %gallery-caption
.gallery-item:hover &
@extend %gallery-caption.visible
[class*=list] &, .gallery-size-thumbnail &
display: none
<link href="https://codepen.io/mican/pen/xYpoWX" rel="stylesheet" />
<link href="https://codepen.io/mican/pen/yoOYLZ" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.2/photoswipe.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.2/default-skin/default-skin.min.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment