UNPKG

react-image-gallery

Version:

React carousel image gallery component with thumbnail and mobile support

703 lines (605 loc) 17 kB
/** * React Image Gallery - Styles * * Design System: Base-4 spacing scale * Spacing: 2, 4, 8, 12, 16, 20, 24, 32, 48, 64, 80, 96, 120px * * CSS Custom Properties for theming: * --ig-primary-color: Primary/accent color (default: #337ab7) * --ig-white: Icon and text color (default: #fff) * --ig-black: Background color in fullscreen (default: #000) * --ig-background-overlay: Overlay background (default: rgba(0, 0, 0, 0.4)) * --ig-thumbnail-size: Thumbnail dimensions (default: 96px) * --ig-thumbnail-size-small: Thumbnail size on small screens (default: 80px) * --ig-thumbnail-border-width: Thumbnail border width (default: 4px) * --ig-thumbnail-border-width-small: Thumbnail border on small screens (default: 3px) * --ig-bullet-size: Bullet size (default: 4px) * --ig-bullet-size-small: Bullet size on small screens (default: 3px) */ :root { --ig-primary-color: #337ab7; --ig-white: #fff; --ig-black: #000; --ig-background-overlay: rgba(0, 0, 0, 0.4); --ig-thumbnail-size: 96px; --ig-thumbnail-size-small: 80px; --ig-thumbnail-border-width: 4px; --ig-thumbnail-border-width-small: 3px; --ig-bullet-size: 4px; --ig-bullet-size-small: 3px; } /* ========================================================================== SVG Icon Styles ========================================================================== */ .image-gallery-icon { color: var(--ig-white, #fff); transition: all 0.3s ease-out; appearance: none; background-color: transparent; border: 0; cursor: pointer; outline: none; position: absolute; z-index: 4; filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.5)); } @media (hover: hover) and (pointer: fine) { .image-gallery-icon:hover { color: var(--ig-primary-color, #337ab7); } .image-gallery-icon:hover .image-gallery-svg { transform: scale(1.1); } } .image-gallery-icon:focus { outline: 2px solid var(--ig-primary-color, #337ab7); } .image-gallery-using-mouse .image-gallery-icon:focus { outline: none; } /* Fullscreen & Play buttons */ .image-gallery-fullscreen-button, .image-gallery-play-button { bottom: 0; padding: 20px; } .image-gallery-fullscreen-button .image-gallery-svg, .image-gallery-play-button .image-gallery-svg { height: 32px; width: 32px; } @media (max-width: 768px) { .image-gallery-fullscreen-button, .image-gallery-play-button { padding: 16px; } .image-gallery-fullscreen-button .image-gallery-svg, .image-gallery-play-button .image-gallery-svg { height: 24px; width: 24px; } } @media (max-width: 480px) { .image-gallery-fullscreen-button, .image-gallery-play-button { padding: 12px; } .image-gallery-fullscreen-button .image-gallery-svg, .image-gallery-play-button .image-gallery-svg { height: 16px; width: 16px; } } .image-gallery-fullscreen-button { right: 0; } .image-gallery-play-button { left: 0; } /* Top & Bottom navigation */ .image-gallery-top-nav, .image-gallery-bottom-nav { padding: 12px; left: 50%; transform: translateX(-50%); } .image-gallery-top-nav .image-gallery-svg, .image-gallery-bottom-nav .image-gallery-svg { height: 120px; width: 96px; } @media (max-width: 768px) { .image-gallery-top-nav .image-gallery-svg, .image-gallery-bottom-nav .image-gallery-svg { height: 72px; width: 48px; } } @media (max-width: 480px) { .image-gallery-top-nav .image-gallery-svg, .image-gallery-bottom-nav .image-gallery-svg { height: 48px; width: 32px; } } .image-gallery-top-nav[disabled], .image-gallery-bottom-nav[disabled] { cursor: not-allowed; opacity: 0.6; pointer-events: none; } .image-gallery-top-nav { top: 0; } .image-gallery-bottom-nav { bottom: 0; } /* Left & Right navigation */ .image-gallery-left-nav, .image-gallery-right-nav { padding: 48px 12px; top: 50%; transform: translateY(-50%); } .image-gallery-left-nav .image-gallery-svg, .image-gallery-right-nav .image-gallery-svg { height: 120px; width: 64px; } @media (max-width: 768px) { .image-gallery-left-nav .image-gallery-svg, .image-gallery-right-nav .image-gallery-svg { height: 72px; width: 32px; } } @media (max-width: 480px) { .image-gallery-left-nav .image-gallery-svg, .image-gallery-right-nav .image-gallery-svg { height: 48px; width: 24px; } } .image-gallery-left-nav[disabled], .image-gallery-right-nav[disabled] { cursor: not-allowed; opacity: 0.6; pointer-events: none; } .image-gallery-left-nav { left: 0; } .image-gallery-right-nav { right: 0; } /* ========================================================================== Gallery Container ========================================================================== */ .image-gallery { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-tap-highlight-color: transparent; position: relative; /* Prevent mobile overscroll/pull-to-refresh */ overscroll-behavior: none; -webkit-overflow-scrolling: touch; } .image-gallery.fullscreen-modal { background: var(--ig-black, #000); bottom: 0; height: 100%; left: 0; position: fixed; right: 0; top: 0; width: 100%; z-index: 5; } .image-gallery.fullscreen-modal .image-gallery-content { top: 50%; transform: translateY(-50%); } /* ========================================================================== Gallery Content ========================================================================== */ .image-gallery-content { position: relative; line-height: 0; top: 0; } .image-gallery-content.fullscreen { background: var(--ig-black, #000); } .image-gallery-content .image-gallery-slide .image-gallery-image { max-height: calc(100vh - 80px); } .image-gallery-content.image-gallery-thumbnails-left .image-gallery-slide .image-gallery-image, .image-gallery-content.image-gallery-thumbnails-right .image-gallery-slide .image-gallery-image { max-height: 100vh; } /* ========================================================================== Slide Wrapper ========================================================================== */ .image-gallery-slide-wrapper { position: relative; } .image-gallery-slide-wrapper.image-gallery-thumbnails-left, .image-gallery-slide-wrapper.image-gallery-thumbnails-right { display: inline-block; width: calc(100% - 112px); } @media (max-width: 768px) { .image-gallery-slide-wrapper.image-gallery-thumbnails-left, .image-gallery-slide-wrapper.image-gallery-thumbnails-right { width: calc(100% - 88px); } } .image-gallery-slide-wrapper.image-gallery-rtl { direction: rtl; } .image-gallery-swipe { overflow: hidden; /* GPU acceleration */ -webkit-backface-visibility: hidden; backface-visibility: hidden; -webkit-transform: translateZ(0); transform: translateZ(0); touch-action: pan-y pinch-zoom; } /* ========================================================================== Slides ========================================================================== */ .image-gallery-slides { overflow: hidden; position: relative; /* Allow vertical scroll and pinch-zoom; block horizontal pan so JS handles swipe. The browser's built-in direction detection prevents vertical scroll during horizontal swipes. On desktop, wheel/trackpad scroll passes through normally. */ touch-action: pan-y pinch-zoom; /* GPU acceleration for smooth swiping */ -webkit-backface-visibility: hidden; backface-visibility: hidden; contain: layout style paint; isolation: isolate; } /* Flex container that holds all slides and gets transformed */ .image-gallery-slides-container { display: flex; /* GPU acceleration for smooth swiping */ -webkit-backface-visibility: hidden; backface-visibility: hidden; -webkit-transform-style: preserve-3d; transform-style: preserve-3d; will-change: transform; } .image-gallery-slides-container.vertical { flex-direction: column; height: 100%; } .image-gallery-slides-container.vertical .image-gallery-slide { flex: 0 0 100%; height: 100%; min-height: 0; } .image-gallery-slides-container.vertical .image-gallery-slide .image-gallery-image { height: 100%; width: auto; max-width: 100%; } .image-gallery-slide { flex: 0 0 100%; min-width: 0; position: relative; /* GPU acceleration for smooth swiping */ -webkit-backface-visibility: hidden; backface-visibility: hidden; } .image-gallery-slide .image-gallery-image { width: 100%; object-fit: contain; } .image-gallery-slide .image-gallery-description { background: var(--ig-background-overlay, rgba(0, 0, 0, 0.4)); bottom: 72px; color: var(--ig-white, #fff); left: 0; line-height: 1; padding: 12px 20px; position: absolute; white-space: normal; } @media (max-width: 768px) { .image-gallery-slide .image-gallery-description { bottom: 48px; font-size: 0.8em; padding: 8px 16px; } } /* ========================================================================== Bullets ========================================================================== */ .image-gallery-bullets { bottom: 20px; left: 0; margin: 0 auto; position: absolute; right: 0; width: 80%; z-index: 4; text-align: center; } .image-gallery-bullets .image-gallery-bullets-container { margin: 0 auto; padding: 0; display: inline-block; } .image-gallery-bullets .image-gallery-bullets-inner { display: flex; align-items: center; justify-content: flex-start; white-space: nowrap; padding: 2px 0; } .image-gallery-bullets .image-gallery-bullet { appearance: none; background-color: transparent; border: 1px solid var(--ig-white, #fff); border-radius: 50%; box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6); cursor: pointer; margin: 0 4px; outline: none; width: calc(var(--ig-bullet-size, 4px) * 2 + 2px); height: calc(var(--ig-bullet-size, 4px) * 2 + 2px); padding: 0; flex-shrink: 0; transition: all 0.2s ease-out; } @media (max-width: 768px) { .image-gallery-bullets .image-gallery-bullet { margin: 0 3px; width: calc(var(--ig-bullet-size-small, 3px) * 2 + 2px); height: calc(var(--ig-bullet-size-small, 3px) * 2 + 2px); } } @media (max-width: 480px) { .image-gallery-bullets .image-gallery-bullet { width: 8px; height: 8px; } } .image-gallery-bullets .image-gallery-bullet:focus { transform: scale(1.2); background: var(--ig-primary-color, #337ab7); border: 1px solid var(--ig-primary-color, #337ab7); } .image-gallery-bullets .image-gallery-bullet.active { transform: scale(1.2); border: 1px solid var(--ig-white, #fff); background: var(--ig-white, #fff); } @media (hover: hover) and (pointer: fine) { .image-gallery-bullets .image-gallery-bullet:hover { background: var(--ig-primary-color, #337ab7); border: 1px solid var(--ig-primary-color, #337ab7); } .image-gallery-bullets .image-gallery-bullet.active:hover { background: var(--ig-primary-color, #337ab7); } } /* Vertical bullets */ .image-gallery-bullets.image-gallery-bullets-vertical { left: 20px; right: auto; bottom: auto; width: auto; top: 50%; transform: translateY(-50%); } .image-gallery-bullets.image-gallery-bullets-vertical .image-gallery-bullets-inner { flex-direction: column; padding: 0 2px; } .image-gallery-bullets.image-gallery-bullets-vertical .image-gallery-bullet { display: block; margin: 4px 0; } @media (max-width: 768px) { .image-gallery-bullets.image-gallery-bullets-vertical .image-gallery-bullet { margin: 3px 0; } } @media (max-width: 480px) { .image-gallery-bullets.image-gallery-bullets-vertical .image-gallery-bullet { margin: 3px 0; } } /* ========================================================================== Thumbnails Wrapper ========================================================================== */ .image-gallery-thumbnails-wrapper { position: relative; } .image-gallery-thumbnails-wrapper.thumbnails-swipe-horizontal { touch-action: pan-y; } .image-gallery-thumbnails-wrapper.thumbnails-swipe-vertical { touch-action: pan-x; } .image-gallery-thumbnails-wrapper.thumbnails-wrapper-rtl { direction: rtl; } .image-gallery-thumbnails-wrapper.image-gallery-thumbnails-left, .image-gallery-thumbnails-wrapper.image-gallery-thumbnails-right { display: inline-block; vertical-align: top; width: var(--ig-thumbnail-size, 96px); } @media (max-width: 768px) { .image-gallery-thumbnails-wrapper.image-gallery-thumbnails-left, .image-gallery-thumbnails-wrapper.image-gallery-thumbnails-right { width: var(--ig-thumbnail-size-small, 80px); } } .image-gallery-thumbnails-wrapper.image-gallery-thumbnails-left .image-gallery-thumbnails, .image-gallery-thumbnails-wrapper.image-gallery-thumbnails-right .image-gallery-thumbnails { height: 100%; width: 100%; left: 0; padding: 0; position: absolute; top: 0; } .image-gallery-thumbnails-wrapper.image-gallery-thumbnails-left .image-gallery-thumbnails .image-gallery-thumbnail, .image-gallery-thumbnails-wrapper.image-gallery-thumbnails-right .image-gallery-thumbnails .image-gallery-thumbnail { display: block; margin-right: 0; padding: 0; } .image-gallery-thumbnails-wrapper.image-gallery-thumbnails-left .image-gallery-thumbnails .image-gallery-thumbnail + .image-gallery-thumbnail, .image-gallery-thumbnails-wrapper.image-gallery-thumbnails-right .image-gallery-thumbnails .image-gallery-thumbnail + .image-gallery-thumbnail { margin-left: 0; margin-top: 2px; } .image-gallery-thumbnails-wrapper.image-gallery-thumbnails-left, .image-gallery-thumbnails-wrapper.image-gallery-thumbnails-right { margin: 0 4px; } @media (max-width: 768px) { .image-gallery-thumbnails-wrapper.image-gallery-thumbnails-left, .image-gallery-thumbnails-wrapper.image-gallery-thumbnails-right { margin: 0 4px; } } /* ========================================================================== Thumbnails ========================================================================== */ .image-gallery-thumbnails { overflow: hidden; padding: 4px 0; } @media (max-width: 768px) { .image-gallery-thumbnails { padding: 4px 0; } } .image-gallery-thumbnails .image-gallery-thumbnails-container { cursor: pointer; text-align: center; white-space: nowrap; } .image-gallery-thumbnail { display: inline-block; border: var(--ig-thumbnail-border-width, 4px) solid transparent; transition: border 0.3s ease-out; width: var(--ig-thumbnail-size, 96px); background: transparent; padding: 0; } @media (max-width: 768px) { .image-gallery-thumbnail { border: var(--ig-thumbnail-border-width-small, 3px) solid transparent; width: var(--ig-thumbnail-size-small, 80px); } } .image-gallery-thumbnail + .image-gallery-thumbnail { margin-left: 2px; } .image-gallery-thumbnail .image-gallery-thumbnail-inner { display: block; position: relative; } .image-gallery-thumbnail .image-gallery-thumbnail-image { vertical-align: middle; width: 100%; line-height: 0; } .image-gallery-thumbnail.active, .image-gallery-thumbnail:focus { outline: none; border: var(--ig-thumbnail-border-width, 4px) solid var(--ig-primary-color, #337ab7); } @media (max-width: 768px) { .image-gallery-thumbnail.active, .image-gallery-thumbnail:focus { border: var(--ig-thumbnail-border-width-small, 3px) solid var(--ig-primary-color, #337ab7); } } @media (hover: hover) and (pointer: fine) { .image-gallery-thumbnail:hover { outline: none; border: var(--ig-thumbnail-border-width, 4px) solid var(--ig-primary-color, #337ab7); } } @media (hover: hover) and (pointer: fine) and (max-width: 768px) { .image-gallery-thumbnail:hover { border: var(--ig-thumbnail-border-width-small, 3px) solid var(--ig-primary-color, #337ab7); } } /* ========================================================================== Thumbnail Label ========================================================================== */ .image-gallery-thumbnail-label { box-sizing: border-box; color: var(--ig-white, #fff); font-size: 1em; left: 0; line-height: 1em; padding: 5%; position: absolute; top: 50%; text-shadow: 0 2px 2px rgba(0, 0, 0, 0.6); transform: translateY(-50%); white-space: normal; width: 100%; } @media (max-width: 768px) { .image-gallery-thumbnail-label { font-size: 0.8em; line-height: 0.8em; } } /* ========================================================================== Index Display ========================================================================== */ .image-gallery-index { background: var(--ig-background-overlay, rgba(0, 0, 0, 0.4)); color: var(--ig-white, #fff); line-height: 1; padding: 10px 20px; position: absolute; right: 0; top: 0; z-index: 4; } @media (max-width: 768px) { .image-gallery-index { font-size: 0.8em; padding: 5px 10px; } }