Studio 亮相:我们精美的全新代理网站模板

Adam Wathan

我们刚刚发布了 Studio - 一个漂亮的全新代理网站模板,这是我们过去几个月一直在为 Tailwind UI 开发的。

¥We just released Studio — a beautiful new agency website template we've been working on for the last couple of months for Tailwind UI.

我们使用 Next.js、MDX 以及 Tailwind CSS 构建了它,这是我们使用新版 Next.js 应用路由 发布的第一个模板。

¥We built it with Next.js, MDX, and of course Tailwind CSS, and it's the first template we've published using the new Next.js App Router.

设计一个代理模板是一个有趣的项目,因为创意代理机构通常会使用自己的网站来展示一些非常炫酷的定制创意,而当目标是展示自己公司的能力时,使用模板会感觉有点奇怪。

¥Designing an agency template is an interesting project, because creative agencies commonly use their own website to show off some really flashy, bespoke ideas, and using a template just kind of feels strange when the goal is to show what your own company is capable of.

因此,我们尝试以两个目标来设计这个版本,以使其真正对用户有用:

¥So we tried to approach this one with two goals in mind to actually make it useful to people:

  1. 教人们如何制作你在 Flash 代理网站上看到的一些酷炫内容 - 我一直相信,我们的模板作为教育资源的价值与作为普通模板的价值一样(甚至更高),因此我们想利用这个模板来展示我们如何构建你在这些网站上看到的许多酷炫的交互式动画细节。

    ¥Teach people how to do some of the cool stuff you see on flash agency sites — I've always believed our templates are just as (if not more) valuable as an educational resource than as simply templates, so we wanted to use this template as an opportunity to show off how we'd build a lot of the cool interactive and animated details you see on these sorts of sites.

  2. 为不出售设计的代理机构设计 - 很多代理机构只专注于工程工作,而这些公司很多时候都难以在设计方面脱颖而出。我们尝试以一种不依赖大量设计作品截图和其他内容来获得美观的方式设计此模板,以便专注于代码的机构可以将其作为自己网站的起点。

    ¥Design it for agencies that don't sell design — there are a lot of agencies out there who just focus on engineering work, and a lot of the time those companies struggle to stand out design-wise. We tried to design this template in a way that it didn't depend on tons of screenshots of design work and stuff to look good, so that an agency that focuses on code could use it as a starting point for their own site.

我认为我们最终的方案完美地实现了这两个目标,我对最终的成果感到非常自豪。

¥I think what we came up with nailed these two goals and I'm really proud of how it all turned out.

一如既往地查看 现场预览 以获得完整体验 - 它包含大量精彩细节,你必须在浏览器中查看才能真正体会到。

¥Check out the live preview as always for the full experience — there are tons of cool details in this one that you have to see in the browser to really appreciate.


赏心悦目的动画(Delightfully animated)

¥Delightfully animated

代理网站有一条不成文的规则,那就是必须引人注目。我们没有完全替换鼠标光标,也没有用 WebGL 渲染整个网站,但我们确实寻找机会,尽可能巧妙地引入动画和交互功能。

¥One of the unspoken rules of agency websites is that they've gotta be flashy. We didn't go full replace-the-mouse-cursor or render-the-entire-site-with-WebGL but we did look for opportunities to tastefully introduce animations and interactivity wherever we could.

例如,我们围绕 Framer Motion 的一些功能构建了一个基于组件的轻量级声明式 API,以便轻松实现滚动触发的入口动画:

¥For instance, we built a light declarative component-based API around some features of Framer Motion to make it easy to do scroll-triggered entrance animations:

这些类型的动画的创作体验非常出色 - 只需用 FadeInFadeInStagger 组件封装你想要淡入的内容即可:

¥The authoring experience for these types of animations turned out really nice — just wrap the stuff you want to fade in with a FadeIn or FadeInStagger component and you're in business:

function Clients() {
return (
<div className="mt-24 rounded-4xl bg-neutral-950 py-20 sm:mt-32 sm:py-32 lg:mt-56">
<Container>
<FadeIn className="flex items-center gap-x-8">
<h2 className="font-display text-center text-sm font-semibold tracking-wider text-white sm:text-left">
We’ve worked with hundreds of amazing people
</h2>
<div className="h-px flex-auto bg-neutral-800" />
</FadeIn>
<FadeInStagger faster>
<ul role="list" className="mt-10 grid grid-cols-2 gap-x-8 gap-y-10 lg:grid-cols-4">
{clients.map(([client, logo]) => (
<li key={client}>
<FadeIn>
</FadeIn>
</li>
))}
</ul>
</FadeInStagger>
</Container>
</div>
);
}

我们还为徽标添加了一个漂亮的小动画,鼠标悬停时,标记会填充纯色:

¥We also added this nice little animation to the logo where the mark is filled with a solid color on hover:

这个小细节看起来很小,但有趣的是,如果没有客户端导航,你实际上无法做到这一点,因为点击徽标返回主页时动画会重新运行。使用像 Next.js 这样的框架,我们可以在鼠标悬停时保持徽标填充,即使在 URL 发生变化时也是如此,这感觉好多了。

¥This little detail looks small but interestingly you can't really do it without client-side navigation, because the animation would re-run when clicking the logo to go back to the homepage. Using a framework like Next.js, we're able to keep the logo filled in while hovering, even across URL changes, which feels a lot nicer.

菜单抽屉动画也非常出色,打开时会将整个页面向下推:

¥The menu drawer animation turned out really nice as well, pushing the whole page down when it opens:

如果你仔细观察,就会发现徽标和按钮的颜色变化并非偶然 - 它实际上是由向下滑动的表单的位置精确控制的,并且当表单的边缘与徽标相交时,徽标实际上是部分白色,部分黑色。

¥If you look closely, the logo and button don't just naively change color either — it's actually driven precisely by the position of the sheet that's sliding down, and the logo is actually partially white and partially black at the same time when the edge of the sheet is intersecting with it.

另一个我非常喜欢的细节是我们为案例研究页面上的图片设计的交互:

¥Another detail I really love is this interaction we came up with for the images on the case study pages:

我们希望整个网站呈现黑白色调,但一直显示黑白图片感觉不对。因此,我们设计了这种处理方式:图片从黑白开始,随着滚动图片接近屏幕中心,饱和度会以动画形式恢复。我们还在鼠标悬停时显示全彩图片。

¥We wanted the whole site to feel black and white, but showing black and white images all of the time didn't feel right. So we came up with this treatment where the image starts off black and white, and the saturation animates back in as the image gets close to the center of the screen when scrolling. We also show the full color image on hover.

我们还精心设计了所有这些动画,并考虑到了患有前庭运动障碍的人以及他们对这类大型动画的敏感度。使用 Framer Motion 的 useReducedMotion 钩子和 Tailwind 中的 motion-safe 变体,我们可以执行诸如有条件地禁用导航菜单动画,并将滚动驱动的入口动画限制为不透明度,以使屏幕上的内容不会移动。

¥We were also careful to try and implement all of these animations in a way that's mindful of people with vestibular motion disorders and are sensitive to these types of big animations. Using Framer Motion's useReducedMotion hook and the motion-safe variant in Tailwind, we do things like conditionally disable the navigation menu animation, and limit the scroll-driven entrance animations to opacity only so things aren't moving on the screen.


以开发者为中心的案例研究和博客工作流程(Developer-centric case study and blog workflow)

¥Developer-centric case study and blog workflow

Studio 同时支持 案例研究博客文章,如果你使用过我们的其他模板,你可能已经猜到了,我们以此为契机将 MDX 集成到项目中。

¥Studio includes support for both case studies and blog posts, and as you might have guessed if you've played with any of our other templates, we used this an excuse to integrate MDX into the project.

以下是基本案例研究的示例 - 主要撰写于 Markdown 包含一些通用元数据,并支持将自定义组件混合到内容中:

¥Here's an example of what a basic case study looks like — authored mostly in markdown with some common metadata and support for custom components mixed in to the content:

import logo from "@/images/clients/phobia/logomark-dark.svg";
import imageHero from "./hero.jpg";
import imageJennyWilson from "./jenny-wilson.jpeg";
export const caseStudy = {
client: "Phobia",
title: "Overcome your fears, find your match",
description:
"Find love in the face of fear — Phobia is a dating app that matches users based on their mutual phobias so they can be scared together.",
summary: [
"Find love in the face of fear — Phobia is a dating app that matches users based on their mutual phobias so they can be scared together.",
"We worked with Phobia to develop a new onboarding flow. A user is shown pictures of common phobias and we use the microphone to detect which ones make them scream, feeding the results into the matching algorithm.",
],
logo,
image: { src: imageHero },
date: "2022-06",
service: "App development",
testimonial: {
author: { name: "Jenny Wilson", role: "CPO of Phobia" },
content:
"The team at Studio went above and beyond with our onboarding, even finding a way to access the user’s microphone without triggering one of those annoying permission dialogs.",
},
}
;
export const metadata = {
title: `${caseStudy.client} Case Study`,
description: caseStudy.description,
}
;
## Overview
Noticing incredibly high churn, the team at Phobia came to the conclusion that, instead of having a
fundamentally flawed business idea, they needed to improve their onboarding process.
Previously users selected their phobias manually but this led to some users selecting things they
weren’t actually afraid of to increase their matches.
To combat this, we developed a system that displays a slideshow of common phobias during
onboarding. We then use malware to surreptitiously access their microphone and detect when they
have audible reactions. We measure the pitch, volume and duration of their screams and feed that
information to the matching algorithm.
The next phase is a VR version of the onboarding flow where users are subjected to a series of
scenarios that will determine their fears. We are currently developing the first scenario, working
title: “Jumping out of a plane full of spiders”.
## What we did
<TagList>
<TagListItem>Android</TagListItem>
<TagListItem>iOS</TagListItem>
<TagListItem>Malware</TagListItem>
<TagListItem>VR</TagListItem>
</TagList>
<Blockquote author={{ name: "Jenny Wilson", role: "CPO of Phobia" }} image={{ src: imageJennyWilson }}>
The team at Studio went above and beyond with our onboarding, even finding a way to access the user’s microphone
without triggering one of those annoying permission dialogs.
</Blockquote>
<StatList>
<StatListItem value="20%" label="Churn rate" />
<StatListItem value="5x" label="Uninstalls" />
<StatListItem value="2.3" label="App store rating" />
<StatListItem value="8" label="Pending lawsuits" />
</StatList>

此模板的所有排版样式均为完全自定义,这次我们采用了与以往略有不同的方法 - 我们没有编写大量复杂的 CSS 以避免排版样式与 MDX 中的任何自定义组件冲突,而是创建了一个名为 remark-rehype-wrap 的小插件,它可以使用封装器元素包裹大块的 Markdown 内容。

¥All of the typography styles for this template are totally custom and we took a bit of a different approach this time than we have in the past — instead of writing a bunch of complex CSS to avoid our typography styles clashing with any custom components in the MDX, we created a little remark plugin called remark-rehype-wrap that makes it possible to wrap chunks of Markdown content with a wrapper element.

这样,我们就可以用 typography 类封装任何原生 Markdown 内容,但要确保文档中的任何自定义组件都未被封装,而不是试图以忽略树中这些部分的方式编写 CSS。

¥This way, we could wrap anything that was vanilla Markdown content with a typography class, but make sure any custom components in the document were simply not wrapped, rather than try to craft the CSS in such a way that it ignores those parts of the tree.

这两种方法都完全可行,但尝试新想法并看看能学到什么总是很有趣的。我很好奇,未来基于 CSS 新增的 样式查询 功能的解决方案会是什么样子!

¥Both approaches totally work but it's always fun to try new ideas and see what you learn. I'm curious to see what a solution based on the new style queries feature coming to CSS might look like in the future too!


这就是 Studio!把它拆下来,拆开看看,看看你是否学到了一些新的技巧。

¥So that's Studio! Pull it down, tear it apart, and see if you learn a couple of new tricks.

与我们所有的模板一样,它包含一次性购买的 Tailwind UI 全面访问 许可证,这是支持我们在 Tailwind CSS 上工作并使我们能够在未来几年继续构建出色产品的最佳方式。

¥Like all of our templates, it's included with a one-time purchase Tailwind UI all-access license, which is the best way to support our work on Tailwind CSS and make it possible for us to keep building awesome stuff for years to come.

TailwindCSS v4.1 中文网 - 粤ICP备13048890号