<div class="basic-quote-container">
<section class="basic-quote basic-quote-left-align basic-quote-default">
<div class="basic-quote-backdrop basic-quote-pattern basic-quote-pattern-diagonal basic-quote-pattern-strawberry">
<div class="basic-quote-pattern-background" role="presentation"></div>
</div>
<div class="basic-quote-panel">
<div class="basic-quote-image-container">
<div class="basic-quote-mobile-backdrop basic-quote-pattern basic-quote-pattern-diagonal basic-quote-pattern-strawberry">
<div class="basic-quote-pattern-mobile-background" role="presentation"></div>
<img src="../../images/quote-block/example-3-stock-image.jpg" alt="A printing machine, printing yellow labels" />
</div>
</div>
<div class="basic-quote-panel-inner">
<div class="quote-text">
<p>Lecturers constantly challenged us. We were encouraged to speak in front of more and more people, which made speaking in front of five ‘dragons’ a piece of cake! OK, maybe not a piece of cake, but it definitely helped me win over Jenny
Campbell.</p>
</div>
<div class="quote-name">Ed Hollands</div>
<div class="quote-title">Business Studies BA graduate. Ed won a £30,000 investment on Dragons’ Den</div>
</div>
</div>
</div>
</section>
</div>
<div class="basic-quote-container">
<section class="basic-quote basic-quote-left-align basic-quote-default">
<div class="basic-quote-backdrop basic-quote-pattern basic-quote-pattern-diagonal basic-quote-pattern-{{patternColour}}">
<div class="basic-quote-pattern-background" role="presentation"></div>
</div>
<div class="basic-quote-panel">
<div class="basic-quote-image-container">
<div class="basic-quote-mobile-backdrop basic-quote-pattern basic-quote-pattern-diagonal basic-quote-pattern-{{patternColour}}">
<div class="basic-quote-pattern-mobile-background" role="presentation"></div>
<img src="{{ image.path | path }}"{% if image.srcset %} srcset="{% for src in image.srcset %}{{ src.path | path }} {{ src.width }}w, {% endfor %}{{ image.path | path }}"{% endif %} alt="{{ image.alt }}" />
</div>
</div>
<div class="basic-quote-panel-inner">
<div class="quote-text"><p>{{quote}}</p></div>
<div class="quote-name">{{name}}</div>
<div class="quote-title">{{title}}</div>
</div>
</div>
</div>
</section>
</div>
{
"name": "Ed Hollands",
"label": "Headshot Primary Blue",
"context": {
"patternColour": "primary-blue",
"quote": "It was the skills, attitude and professionalism that my course bestowed upon me that allowed me to thrive, and to work over and above expectations to set myself up for a promising future.",
"name": "Ryan Wheeler",
"title": "Architectural Technology and Practice BSc",
"image": {
"path": "/images/quote-block/example-1-headshot.jpg",
"alt": "Headshot of Ryan Wheeler in a hardhat and flourescent jacket on a building site"
}
},
"patternColour": "strawberry",
"quote": "Lecturers constantly challenged us. We were encouraged to speak in front of more and more people, which made speaking in front of five ‘dragons’ a piece of cake! OK, maybe not a piece of cake, but it definitely helped me win over Jenny Campbell.",
"title": "Business Studies BA graduate. Ed won a £30,000 investment on Dragons’ Den",
"image": {
"path": "/images/quote-block/example-3-stock-image.jpg",
"alt": "A printing machine, printing yellow labels"
}
}
// defining the colours as a collection allows us to loop through them and generate classnames based on the keys
$basic-quote-pattern-colours: (
mid-blue: $mid-blue,
strawberry: $strawberry,
yellow: $yellow,
primary-blue: $primary-blue,
turquoise: $turquoise,
orange: $orange,
green: $green,
green-blue: $green-blue
);
// pictures used should be fixed at a 4x3 ratio (0.66) so this value is used for the sake of readability in calculations
$image-aspect-ratio: .66;
// the image and pattern backgrounds are positioned absolutely so that they can be overlapped by the panel itself
// but the panel might not be tall enough to show all of the background image. We need to set a min-height on the
// container panel to get around this. The min-height should always be the height of the image (and no more) and
// because we reliably know the viewport width and the aspect ratio of the image, we can work this out.
//
// 100% viewport width - (40px margin * 2) - 10px gutter = the available space of 16 columns
// available space divided into the number of columns = the image width
// image width * aspect ratio of 4/3 = the image height
$gutter: 10px;
$margin: $max-size; // max-size comes from the fluid-margins calculations elsewhere. but above ipad portrait this is always 40px
$max-width: 100vw;
$total-columns: 16;
$image-columns: 11;
$width-ratio: $image-columns / $total-columns;
// height = 100% viewport width * image aspect ratio - the margins either side of the image
$image-height-mobile: #{'calc(' + 100vw * $image-aspect-ratio + ' + ' + fluid-margin(true) + ')'};
// on tablet devices, the image width is 11 columns
// I'm sorry, 130px is a magic number to make this work and I don't know why.
$image-height-tablet: #{'calc((((' + $max-width + ' - (130px)) * (' + $width-ratio + ')) - ' + $gutter + ') * ' + $image-aspect-ratio + ')'};
// on desktop devices, the image width is 9 columns
$image-columns: 9;
$width-ratio: $image-columns / $total-columns;
// I'm sorry, 60px is a magic number to make this work and I don't know why.
$image-height-desktop: #{'calc((((' + $max-width + ' - (60px)) * (' + $width-ratio + ')) - ' + $gutter + ') * ' + $image-aspect-ratio + ')'};
// the grid is capped at 1700px wide, so above that screen size we need to cap our max width calculations by using a fixed px instead of viewport width
$max-width: 1780px;
// I'm sorry, 60px is a magic number to make this work and I don't know why.
$image-height-large-desktop: #{'calc((((' + $max-width + ' - (60px)) * (' + $width-ratio + ')) - ' + $gutter + ') * ' + $image-aspect-ratio + ')'};
// use to size the content like the lost-grid columns logic, but without the pseudo-element creation to make things difficult.
@mixin flexbox-width-without-columns($columns, $total) {
flex-basis: 0 0 #{'calc(99.9% * ' + ($columns/$total) + ' - (' + $gutter + ' - ' + $gutter + ' * ' + ($columns/$total) + '))'};
width: #{'calc(99.9% * ' + ($columns/$total) + ' - (' + $gutter + ' - '+$gutter+' * ' + ($columns/$total) + '))'};
max-width: #{'calc(99.9% * ' + ($columns/$total) + ' - (' + $gutter + ' - ' + $gutter + ' * ' + ($columns/$total) + '))'};
}
.basic-quote {
display: flex;
position: relative;
align-items: flex-start;
justify-content: flex-end;
lost-column: 8/8;
lost-align: top-right;
.quote-text {
@include responsive('font-size', 20px, 28px, 768px, 1024px);
font-weight: bold;
color: $primary-blue;
p:before {
content: open-quote;
}
p:after {
content: close-quote;
}
p {
@include for-tablet-portrait-up {
margin: 30px;
}
margin: 0;
padding-bottom: 30px;
margin-bottom: 0;
border-bottom: 3px solid $light-grey;
}
}
.quote-name {
@include for-tablet-portrait-up {
margin-left: 30px;
padding-top: 0;
}
padding-top: 30px;
margin: 0;
@include responsive('font-size', 18px, 18px, 768px, 1024px);
font-weight: bold;
color: $primary-blue;
}
.quote-title {
@include responsive('font-size', 17px, 17px, 768px, 1024px);
@include for-tablet-portrait-up {
margin-left: 30px;
}
margin: 0;
}
// on mobile (default) we don't need a minimum height, because we handle this with a margin top/bottom on the panel instead
@include for-largerthan-ipad-portrait {
lost-offset: 1/16;
lost-column: 14/16;
}
&-container {
@include margin-medium;
width: 100%;
}
&-blue,
&-black {
.basic-quote-panel {
background: $primary-blue;
&,
h2 {
color: $white;
}
&-inner {
margin-right: 20px;
margin-left: 20px;
.button {
margin-bottom: px-to-em(18, 16);
}
@include for-tablet-portrait-up {
margin-right: 0;
margin-left: 0;
.button {
margin-bottom: 0;
}
}
}
}
}
&-black {
.basic-quote-panel {
background: $black;
.button {
.button-overlay {
color: $black;
}
}
}
}
&-right-align {
lost-align: top-left;
}
&-panel {
position: relative;
background: $white;
padding: 0;
// on mobile the absolutely positioned background should appear above the panel.
// we can achieve that by adding a margin to the top of the panel which is equal to the height of the image
margin-top: 28px;
&-inner {
margin-top: 1.125rem;
@include for-tablet-portrait-up {
lost-column: 9/13 0;
}
lost-column: 1/1 0;
// for accessiblity we need to use an h2, but want it to look like an h3
h2 {
@extend .h3;
}
.button {
margin-bottom: 0px;
}
}
@include for-tablet-portrait-up {
display: flex;
flex-wrap: wrap;
lost-utility: clearfix;
//@include flexbox-width-without-columns(7.5, 16);
margin-left: 20px;
margin-right: 20px;
margin-top: 20px;
.basic-quote-right-align & {
margin-right: 20px;
}
&-inner {
margin-bottom: 30px;
margin: 0;
}
}
@include for-largerthan-ipad-portrait {
display: flex;
flex-wrap: wrap;
lost-utility: clearfix;
$single-column-width: #{"calc(" + 1 / 13 * 100 + "% + (10px / 14))"};
@include flexbox-width-without-columns(13, 13);
margin: $margin-small;
margin-bottom: 0;
.basic-quote-right-align & {
margin-right: 20px;
margin-left: $single-column-width;
}
}
}
&-backdrop {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 70%;
max-height: 18rem;
justify-content: flex-start;
display: none;
@include for-tablet-portrait-up {
display: flex;
bottom: 35%;
overflow: hidden;
.basic-quote-right-align & {
justify-content: flex-end;
}
}
@include for-tablet-portrait-up {
max-height: $image-height-tablet;
}
@include for-largerthan-ipad-portrait {
display: flex;
max-height: $image-height-desktop;
}
@media (min-width: 1780px) {
max-height: $image-height-large-desktop;
}
}
&-image-container {
$single-column-width: #{"calc(" + 1 / 13 * 100 + "% + (10px / 14))"};
margin-bottom: 0;
font-size: 0;
position: relative;
img {
position: relative;
background-color: transparent;
padding-right: 30px;
padding-top: 30px;
max-width: 100%;
width: 100%;
@include for-tablet-portrait-up {
background-color: $white;
padding: 0;
}
}
@include for-tablet-portrait-up {
lost-column: 4/13 0 0;
lost-align: top-left;
margin: 0;
}
@include for-largerthan-ipad-portrait {
lost-column: 4/13 0 0;
lost-align: top-left;
margin: 0;
}
}
&-pattern {
&-background {
position: absolute;
display: flex;
flex: 1;
width: 75%;
height: 100%;
top: 0;
right: 0;
bottom: 15%;
}
&-img {
margin: 10px;
}
&-mobile-background {
position: absolute;
top: 0;
right: 0;
bottom: 15%;
left: 15%;
}
@include for-tablet-portrait-up {
&-background {
width: 100%;
top: 0;
left: 0;
right: 0;
}
&-mobile-background {
display: none;
}
}
@each $item, $colour in $basic-quote-pattern-colours {
&-#{$item} {
&.basic-quote-pattern-zigzag {
.basic-quote-pattern-background, .basic-quote-pattern-mobile-background {
@include pattern-zigzag($colour);
}
}
&.basic-quote-pattern-diagonal {
.basic-quote-pattern-background, .basic-quote-pattern-mobile-background {
@include pattern-diagonal($colour);
}
}
&.basic-quote-pattern-weave {
.basic-quote-pattern-background, .basic-quote-pattern-mobile-background {
@include pattern-weave($colour);
}
}
}
}
}
}
An image with a quote, a name and a title wrapped in a pattern block.
Responsive images are supported through use of the srcset property, which combine an image path and a target screen width at which the image should be displayed.