Sprout Social Index

Each year, Sprout Social uses its position as a leader in the social media industry to distill vast quantities of data about social media marketing into a beautiful and digestible report on marketing trends and predictions. This report is called the Sprout Social Index. You can think of it as a sort of annual Reader's Digest for social media marketing professionals.

In 2022 we designed and launched a microsite geared toward garnering attention from the media and our social audience to promote the Index and highlight key "teaser" data to encourage users to take a deeper dive into the downloadable Index report and attend its associated webinars. The development and deployment of the microsite for the 2022 Index was one of the first large projects that I took on at Sprout Social.

Development and Collaboration

As the lead developer on this project, I was brought in early for the visual language ideation steps that inspired the designs that ultimately made their way onto the finished page. Because the Index is a special outlier in Sprout Social's marketing efforts, a bespoke, retrofuturist design was developed to be built on top of and augment Sprout Social's strong, in-house design patterns.

In practice, I used our established typescale and spacing tokens as a starting point while experimenting with textures, gradients, and drop shadow elements not found anywhere else in our visual toolkit. The blended use of a pre-built design framework with new and bespoke styles meant that executing this page's finished design transformed the typical design-develop-review handoff process into a collaborative and fun working relationship with an in-house designer to deliver a gorgeous landing page that drove report downloads and generated leads and webinar signups. Stakeholders were excited to share the finished result across the internet and I am proud to make a place for it in my web development portfolio.

The various textures and layered elements pushed my frontend development skills to their limits, and while there are a lot of page elements that required interesting and novel solutions to execute, I want to focus on the CSS Gradient Drop Shadow effect I utilized in multiple places across the page to help data points stand out.

CSS Gradient Drop Shadows

One of the page elements I really enjoyed bringing to life was this little infographic component that had a textured gradient background:

INFOGRAPHIC

The markup wasn't very complicated:

<div class="container">
  <div class="top">
    67% of marketers anticipate investing at least a quarter of their budgets into a metaverse/AR/VR social strategy
  </div>
  <div class="bottom"></div>
</div>

There was a container <div> with the class container, and inside of that, two child <div>s. The first child <div> would have text content (or, like in other places on the page, a graph or infographic image) and sit on top. I gave this one the class top. The second child <div> did not have any content, but would be styled with the gradient and sit underneath the .top <div>. I gave that one the class bottom.

The only other thing to call out before diving into the actual layout approaches is that the "67%" text had a larger font size and a different font family than the rest of the text. To achieve that, I wrapped it in a <span> tag with the class figure to give that numeric figure some specific styling.

Here was the starter markup in full:

<div class="container">
  <div class="top">
    <span class="figure">67%</span>of marketers anticipate investing at least a quarter of their budgets into a metaverse/AR/VR social strategy
  </div>
  <div class="bottom"></div>
</div>

And here was the CSS that I started with:

html {
  box-sizing: border-box;
  height: 100%;
  font-family: Proxima Nova,proxima-nova,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Helvetica,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;
  font-size: 16px;
  line-height: 24px;
}

*, *:before, *:after {
  box-sizing: inherit;
}

body {
  min-height: 100%;
  width: 100%;
  background-color: black;
  font-weight: 300;
  display: flex;
  align-items: center;
  justify-content: center;
}

.figure {
  display: block;
  font-size: 43px;
  line-height: 50.6667px;
  font-family: Recoleta,recoleta,proxima-nova,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Helvetica,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol
}

Positioning Challenge

The main thing that I had to accomplish was stacking the two <div>s with a little bit of left and bottom offset spacing to achieve the layered effect. I tried out two different approaches to get there, the first using a combination of position: relative; and position: absolute; elements and the second using display: grid; and setting the <div>s within the grid area.

Both of these approaches created a stacking context out of the whole HTML block, so I was able to use z-index to achieve z-axis layers.

Here is a little diagram of the overall problem space:

A diagram showing the two divs, stacked on top of one another, with a 20px offset and the z-indexes that allow for one div to be higher up in the dom than the other div.

Absolute Positioning Approach

To achieve this using absolute positioning, I first needed to give the .container <div> a defined height and width and relative positioning:

.container {
  width: 250px;
  height: 250px;
  position: relative;
}

With the overall container set to position: relative; I could now absolutely position the two child <div>s within it. I gave the .top <div> a z-index: 2; and vertically positioned it to the top of the .container <div> and horizontally positioned it 20px in from the left:

.top {
  width: 100%;
  height: 100%;
  border-radius: 20px;
  background-color: white;
  padding: 20px;
  z-index: 2;
  position: absolute;
  top: 0;
  left: 20px;
}

This achieved the following:

A diagram showing how the top div is absolute positioned.

I then gave the .bottom <div> a lower z-index than the .top <div> (z-index: 1;), and vertically positioned it 20px in from the top and horizontally positioned it directly on the left side of the .container <div>:

.bottom {
  width: 100%;
  height: 100%;
  border-radius: 20px;
  background-color: #a1d2f8;
  background-image: linear-gradient(117.64deg,#a1d2f8 10%,#0a3960 60.35%);
  z-index: 1;
  position: absolute;
  top: 20px;
  left: 0;
}

This achieved the following (pictured with .bottom overlayed on .top, but the z-index values would actually have it the other way around):

A diagram showing how the bottom div is absolute positioned.

The two <div>s switching off the 20 pixel inset top and left positioning, in combination with the designated z-indices allowed me to achieve the offset and stacked effect:

You may notice that the .container <div> was given the width and height of 250px and that both the .top and .bottom <div>s were instructed to take up 100% of that available space. The problem this presents is that position: absolute; takes its specified elements out of the flow of the document. While the two child <div>s do inherit that 250px width and height from their parent <div>, the whole thing is not actually contained within the 250px dimensions of the parent. The 20px offset positioning winds up making the whole thing more like 270px by 270px.

Since the dimensions of the .container <div> were hard coded to 250px by 250px for this example, it wouldn't be too difficult to calculate the difference for the dimensions of the child elements to make them fit. However, within the structure of a larger page where I was dealing with variable viewport widths, I couldn't rely on a known width or height to calculate the difference. This approach meant that at certain screen sizes, or when placed next to larger content, the whole element would render in inconsistent and unpredictable dimensions. To solve this problem, I ditched the absolute positioning approach for an approach that used display: grid;.

Grid Approach

A lot of styles from the Absolute Positioning approach carried over here. The .container <div> had the same 250px height and width, the .top and .bottom <div>s still took up 100% of that space and had the same 20px border-radius. .top had the same white background-color and 20px padding, and .bottom had the gradient:

.container {
  width: 250px;
  height: 250px;
}

.top {
  width: 100%;
  height: 100%;
  border-radius: 20px;
  background-color: white;
  padding: 20px;
}

.bottom {
  width: 100%;
  height: 100%;
  border-radius: 20px;
  background-color: #a1d2f8;
  background-image: linear-gradient(117.64deg,#a1d2f8 10%,#0a3960 60.35%);
}

In order to establish a grid layout, I applied display: grid; to the .container <div>, making it a grid container:

.container {
  width: 250px;
  height: 250px;
  display: grid;
}

Having established my grid container, I then defined on that container the row and column layout that I wanted. To achieve this layout...

A diagram showing the two divs, stacked on top of one another, with a 20px offset and the z-indexes that allow for one div to be higher up in the dom than the other div.

...I told the grid to have two 20px columns on either side of a middle column that took up the rest of the remaining available space. I did this like so:

.container {
  width: 250px;
  height: 250px;
  display: grid;
  grid-template-columns: 20px 1fr 20px;
}

The 1fr unit signified a flex unit that took up all of the remaining space in the grid layout. Since there were two 20px columns in a <div> that was 250px wide, then this middle column took up 210px (setting aside any other gap or spacing values, which were not present here). If container were to get any larger or smaller, the 1fr would get larger or smaller right along with it while the 20px <div>s stay the same size.

This achieved the following:

A diagram showing how the grid columns distribute space horizontally.

I did the same thing with rows to fill out the vertical space:

.container {
  width: 250px;
  height: 250px;
  display: grid;
  grid-template-columns: 20px 1fr 20px;
  grid-template-rows: 20px 1fr 20px;
}

This achieved the following:

A diagram showing how the grid rows distribute space vertically.

With my grid container in place and set up with rows and columns, I started laying out the child <div>s inside of it. Like with position: absolute;, display: grid; established a stacking context, so the same z-index values for the .top and .bottom <div>s worked the same here. As for positioning the actual grid items, I told each <div> which grid tracks to occupy by designating their start and end spots using grid lines.

Here is a look at the .top <div>:

.top {
  width: 100%;
  height: 100%;
  border-radius: 20px;
  background-color: white;
  padding: 20px;
  z-index: 2;
  grid-column: 2 / -1;
  grid-row: 1 / 3;
}

grid-column: 2 / -1; handled the horizontal positioning, telling the .top <div> to begin at the second vertical grid line (2) and finish at the last vertical grid line (-1). This created the effect that it was inset 20px from the left but extended to the end of the grid container.

This achieved the following:

A diagram showing how the top div grid item occupies the designated horizontal space.

grid-row: 1 / 3; handled the vertical positioning, telling the .top <div> to begin at the first horizontal grid line (1) and finish at the third horizontal grid line (3); this left that last 20px at the bottom of the .container <div> available for the gradient to peek through.

A diagram showing how the top div grid item occupies the designated vertical space.

Here is a look at the .bottom <div>:

.bottom {
  width: 100%;
  height: 100%;
  border-radius: 20px;
  background-color: #a1d2f8;
  background-image: linear-gradient(117.64deg,#a1d2f8 10%,#0a3960 60.35%);
  z-index: 1;
  grid-column: 1 / 3;
  grid-row: 2 / -1;
}

grid-column: 1 / 3; told the .bottom <div> to begin at the first vertical grid line (1) and extend horizontally to the third vertical grid line (3), taking up the open space on to the left of the .top <div>. grid-row: 2 / -1; told it to begin at the second horizontal grid line (2) and extend vertically down to the last horizontal grid line (-1), again taking up the empty space left by the positioning of the .top grid.

Putting it all together, here was the final result:

The great part about this approach was that, unlike position: absolute;, display: grid; didn't take its page elements out of the document flow. Even accounting for the 20px offsets, the full width of this whole component layout was actually, predictably, 250px by 250px (or whatever other width and height I would want to give it). This meant that I could add this component wherever I needed to throughout the page, swap out the content or the gradient values to best fit the design, and know that it would fit the necessary dimensions without overflowing.

I've included screenshots below of the finished product at desktop and tablet viewport sizes. I hope you enjoyed this post about how I tackled this little grid drop shadow component styling problem.

Screenshots

The desktop view of the Sprout Social Index microsite.

The tablet view of the Sprout Social Index microsite.