<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-green">
<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-green">
<div class="basic-quote-pattern-mobile-background" role="presentation"></div>
<img src="../../images/quote-block/example-2-non-headshot.jpg" alt="A printing machine, printing yellow labels" />
</div>
</div>
<div class="basic-quote-panel-inner">
<div class="quote-text">
<p>We have been very impressed with the Invest to Grow team - their clear guidance and expertise from day one has been second to none. Without them, we would have not been able to build the business to where it is now.</p>
</div>
<div class="quote-name">Matt Francklow</div>
<div class="quote-title">Managing Director, Creation Reprographics</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": "Matt Francklow",
"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": "green",
"quote": "We have been very impressed with the Invest to Grow team - their clear guidance and expertise from day one has been second to none. Without them, we would have not been able to build the business to where it is now.",
"title": "Managing Director, Creation Reprographics",
"image": {
"path": "/images/quote-block/example-2-non-headshot.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.