Props and styling
Generated components accept normal React props. Use Framer properties to change content and behavior, then use className, style, or your own stylesheet for application-specific presentation.
Pass component properties
Framer property controls become props on the generated component. For example:
import Button from "./framer/components/button";
export function HeroButton() {
return (
<Button
buttonText="Start a project"
variant="Primary Button"
link="/contact"
newTab={false}
className="hero-button"
/>
);
}The exact props depend on the published component. Common controls include text, links, icons, borders, visibility flags, and variants. In a TypeScript project, the generated facade provides autocomplete and catches unsupported prop names or variant values.
Here is a content-driven card example:
import SmallContactCard from "./framer/components/small-contact-card";
export function ContactCard() {
return (
<SmallContactCard
title="Reach out to us"
description="Need assistance? Drop us a message anytime."
linkText="hello@example.com"
link="mailto:hello@example.com"
/>
);
}Use className and style
className is the best choice for reusable rules. style is useful for a value that is specific to one instance:
<Button
className="marketing-button"
style={{ marginTop: 16, maxWidth: 280 }}
buttonText="Get started"
/>.marketing-button {
width: 100%;
border-radius: 999px;
}The inline style applies to the component's outer element. A CSS class can also target the component's rendered children when you need to change a nested element.
Override nested Framer text
Some generated text components set their visible color on a nested paragraph using a Framer CSS variable. Setting color on the outer component may not change that nested text. Give the instance a class and override the variable where the text is rendered:
import TextCycle from "./framer/components/text-cycle";
export function ColoredHeadline() {
return (
<TextCycle
className="red-text-cycle"
text1="Design"
text2="Build"
text3="Create"
/>
);
}.red-text-cycle p {
--framer-text-color: red !important;
}This pattern keeps the generated runtime unchanged. If a component uses a heading, link, or another nested element instead of p, inspect the rendered markup and scope the override to that element.
Keep custom CSS outside framer
Put application styles in your normal stylesheet, such as src/app.css or src/styles.css:
import Button from "./framer/components/button";
import "./framer/styles.css";
import "./app.css";
export default function Page() {
return <Button className="page-button" buttonText="Continue" />;
}.page-button {
margin-inline: auto;
}Do not edit generated runtime files or generated component styles to add product-specific rules. A later reframe add may update those files when the Framer export changes. Your own stylesheet remains stable and makes the boundary clear.
Responsive variants
When an export includes breakpoint-specific variants, use its .Responsive entry point:
import TextCycle from "./framer/components/text-cycle";
export function ResponsiveHeadline() {
return (
<TextCycle.Responsive
variants={{
base: "Text 1",
md: "Text 2",
lg: "Text 3",
}}
className="headline"
/>
);
}The breakpoint names and variant values come from the export. A component without responsive variants can still use its normal variant prop.
Layout around a component
Use a wrapper you own for page-level layout. This avoids coupling your route to generated layout classes:
export function FeatureSection() {
return (
<section className="feature-section">
<div className="feature-copy">
<h2>Build from a real Framer component</h2>
<p>Keep the exported behavior while composing it with your application.</p>
</div>
<Button buttonText="Explore" variant="Primary Button" />
</section>
);
}.feature-section {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
gap: 2rem;
align-items: center;
}
@media (max-width: 640px) {
.feature-section {
grid-template-columns: 1fr;
}
}The generated component remains responsible for its Framer behavior; the wrapper is responsible for where that component sits in your application.