认识 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.

Learn about the Studio template

我们使用 Next.js、MDX,当然还有 Tailwind CSS 构建了它,它是我们发布的第一个使用新 Next.js App Router 的模板。

🌐 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. 教人们如何制作你在闪客网站上看到的一些酷炫内容——我一直认为,我们的模板不仅仅是模板,它们作为教育资源的价值甚至可能更高。所以我们希望利用这个模板来展示我们如何制作这些网站上许多酷炫的互动和动画细节。
  2. 为不做设计销售的机构设计 — 现在有很多机构只专注于工程工作,而这些公司在设计方面往往很难脱颖而出。我们尝试以一种不依赖大量设计作品截图等内容也能看起来不错的方式来设计这个模板,这样专注于编码的机构就可以将其作为自己网站的起点使用。

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

🌐 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)

代理网站的一个潜规则是它们必须看起来非常炫酷。我们没有完全更换鼠标指针或用 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>                  <Image src={logo} alt={client} unoptimized />                </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)

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,};## OverviewNoticing incredibly high churn, the team at Phobia came to the conclusion that, instead of having afundamentally flawed business idea, they needed to improve their onboarding process.Previously users selected their phobias manually but this led to some users selecting things theyweren’t actually afraid of to increase their matches.To combat this, we developed a system that displays a slideshow of common phobias duringonboarding. We then use malware to surreptitiously access their microphone and detect when theyhave audible reactions. We measure the pitch, volume and duration of their screams and feed thatinformation to the matching algorithm.The next phase is a VR version of the onboarding flow where users are subjected to a series ofscenarios that will determine their fears. We are currently developing the first scenario, workingtitle: “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 的小型 remark 插件,使得可以用一个封装元素封装 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.

这样,我们可以给任何普通的 Markdown 内容加上 typography 类,但要确保文档中的任何自定义组件根本不会被封装,而不是尝试设计 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 中文网 - 粤ICP备13048890号