Hey, devs! 👋
As a beginner or mid-level developer, you've probably focused a lot on making your app functional. But have you considered how it feels to use? In this post, we'll explore 9 often-overlooked aspects of UI design that can significantly improve your app's user experience.
Note: The examples use ReactJS and TailwindCSS for example but these principles can be applied anywhere.
1. Mind Your Margins and Padding
Uneven margins and padding are a dead giveaway that someone’s still getting the hang of design. Consistent spacing makes everything look cleaner and more professional.
Quick Fix:
Stick to multiples of 4 for margins and padding (think 4px, 8px, 12px, 16px). It gives your layout a nice rhythm and looks way more polished.
.container {
padding: 16px;
}
.button {
padding: 8px 12px;
}
You don’t need to reinvent the wheel—just keep things even, and it’ll instantly look better.
2. Handle Empty States Like a Boss
Ever opened an app and been met with a blank screen? Yeah, that’s what happens when devs forget to design for the empty state. When there’s no data to show, don’t leave users hanging.
Pro Tip:
Add helpful messages or call-to-action (CTA) buttons to guide users on what to do next.
function TodoList({ todos }) {
if (todos.length === 0) {
return (
<div className="flex h-44 flex-col items-center justify-center rounded border bg-white shadow-sm">
<p className="mb-2 text-gray-600">Nothing here yet! Why not add your first task?</p>
<Button className="mt-2 bg-green-500 hover:bg-green-600">
<Plus className="mr-2 h-4 w-4" />
Add Todo
</Button>
</div>
);
}
// Render todo list
}
Turn an empty screen into an opportunity to engage your users!
3. Always Show Loading States
If your app is doing something in the background, let your users know. Nothing is worse than wondering if a button click even worked or if the app crashed.
Pro Tip:
Use a delayed loading spinner for quick operations, so it doesn’t flash too quickly. Here’s a little trick to add a delay:
function useDelayedLoading(isLoading, delay = 200) {
const [showLoading, setShowLoading] = useState(false);
useEffect(() => {
if (isLoading) {
const timer = setTimeout(() => setShowLoading(true), delay);
return () => clearTimeout(timer);
}
setShowLoading(false);
}, [isLoading, delay]);
return showLoading;
}
// Usage
const showLoading = useDelayedLoading(isLoading);
That way, users don’t see the spinner for super quick tasks, but they’ll get feedback when it’s needed.
4. Keep a Clear Visual Hierarchy
Not everything on your screen has the same importance, right? Make sure your UI reflects that. Use different font sizes, colors, and weights to guide users through the content.
Pro Tip:
Stick to 2-3 font sizes for your main content, and use color sparingly to emphasize key points.
.primary-text {
font-size: 18px;
color: #333;
font-weight: bold;
}
.secondary-text {
font-size: 16px;
color: #666;
}
.tertiary-text {
font-size: 14px;
color: #999;
}
Don’t overcomplicate things—just make sure the user knows what’s important at first glance.
5. Embrace Whitespace, Don’t Fear It
You don’t have to fill every inch of the screen with something. Whitespace (aka negative space) is your friend! It helps your app breathe and makes it easier for users to focus.
Pro Tip:
Increase space between unrelated elements and decrease it between related ones. It’s all about balance.
.section {
margin-bottom: 32px; /* Big gap between sections */
}
.section-title {
margin-bottom: 16px; /* Smaller gap within a section */
}
.list-item {
margin-bottom: 8px; /* Tight gap between list items */
}
Whitespace isn’t wasted space—it’s part of the design!
6. Handle Errors Gracefully
No one likes errors, but they happen. When they do, be helpful. Instead of just saying “Error 404,” give the user context and offer ways to fix it or try again.
Pro Tip:
Make your error messages friendly, clear, and actionable.
function ErrorMessage() {
return (
<div className="rounded border bg-neutral-10 p-6">
<h3 className="text-neutral-8900 mb-2 text-xl font-bold">Oops! Page Not Found</h3>
<p className="mb-4 text-neutral-700">
We couldn't find the page you're looking for.
</p>
<div className="flex flex-row-reverse justify-start gap-2">
<Button className="rounded" variant="default">
Retry
</Button>
<Button className="rounded" variant="ghost">
<ArrowLeft className="mr-2 h-4 w-4" />
Go Back
</Button>
</div>
</div>
);
}
Help users feel like they’re not stuck when things go wrong.
7. Add Tooltips for Long Text & Disabled States
Ever tried to read something in an app that was cut off or tried to interact with a disabled button, only to be left guessing why? This can be frustrating for users, and it’s easily avoidable. Add tooltips (title
attribute) to long text or for disabled elements to provide more context.
Pro Tip:
When text is truncated or a button is disabled, a tooltip can offer users additional information, like what the full text is or why the button is inactive. This keeps the experience smooth and informative.
// Long text tooltip example
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<p
className="w-48 truncate"
title="This is a very long text that gets cut off but has a helpful tooltip"
>
This is a very long text that gets cut off but has a helpful tooltip
</p>
</TooltipTrigger>
<TooltipContent>
<p>This is a very long text that gets cut off but has a helpful tooltip</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
// Disabled button tooltip example
<button disabled title="You need to complete the form before submitting">
Submit
</button>
Adding these tooltips makes your app feel more thoughtful and polished. Small touches like this show you care about the user’s experience.
8. Use Contextual Colors for Feedback
Colors play a crucial role in guiding users through your app. Using the right color for the right situation makes the interface more intuitive and easier to understand. For example, reddish tones for errors, greenish for success, yellowish for warnings, and blueish for informational messages.
Pro Tip:
Stick to established color conventions to avoid confusing your users. Most people recognize red as an error or danger indicator and green as a success marker, so leverage that!
// Example of contextual colors in action
<div className="flex items-center rounded-md border border-red-200 bg-red-100/75 p-3">
<AlertCircle className="mr-2 text-red-700" />
<p className="text-red-800">Error: Something went wrong!</p>
</div>
<div className="flex items-center rounded-md border border-green-400 bg-green-100/75 p-3">
<CheckCircle className="mr-2 text-green-700" />
<p className="text-green-800">Success: Operation completed!</p>
</div>
By following these color conventions, you make it much easier for users to quickly understand what's happening in your app without over-explaining.
This small detail not only helps in making your UI more intuitive but also enhances the visual hierarchy by linking colors with actions and outcomes.
9. Icons Should Enhance, Not Distract
Don’t overload your UI with icons for the sake of it. Every icon should have a clear purpose and enhance the user experience.
Pro Tip:
Keep icons simple, and recognizable, and ensure they match the action they represent.
<Icon name="trash" onClick={deleteItem} />
<Icon name="edit" onClick={editItem} />
Use icons to clarify actions, not clutter your UI.
10. Don’t Reinvent the Wheel — Use Solid UI Libraries
It’s easy to fall into the trap of thinking you have to code everything from scratch. But guess what? You don’t! There are fantastic UI libraries out there like Ant Design, Shadcn UI, Material UI, and Chakra UI that can save you a ton of time and effort. These libraries provide well-tested, accessible, and consistent components, so you can focus on what makes your app unique instead of redoing the basics.
Pro Tip:
If you’re trying to move fast or you’re working on a project with tight deadlines, leverage these libraries. But if you’re building something purely for learning, feel free to dive into the details and build your own components.
import { Button } from 'antd';
function MyApp() {
return <Button type="primary">Click Me</Button>;
}
Using these libraries helps ensure that your app looks polished, functions well, and remains consistent, all while saving you time. You can always customize things later, but starting with a solid foundation helps you move faster.
No need to code a button from scratch when there’s already a beautifully styled, responsive one you can drop right in!
Conclusion
The key to a great UI is attention to detail. These small tweaks—consistent spacing, clear hierarchy, thoughtful empty/loading/error states, and balanced use of whitespace—make a world of difference. Whether you’re working on your first app or your 50th, take the time to polish these areas, and your users will thank you.
Got any thoughts or questions? Let me know, I’m happy to expand on these topics or chat more. Happy coding, and may your apps always feel amazing! ✨
Top comments (38)
Nice and useful recomendations, thanks.
I have recently come across another interesting article full or UI tips with practical examples. I hope you dont mind, if I leave a link here - uxplanet.org/16-ui-design-tips-ba2...
Nice one!
Wow, awesome. Thanks for sharing!
Another couple of tips, regarding forms:
🙌🏼
These are common UX/UI mistakes that I often encounter in my mobile app development career. I've struggled to convince UX/UI designers about the importance of adhering to these best practices in a professional application
it is always pain in my a** to decide how much info regarding error that occurred I want to provide to user... Ofc I always can make sth like: Ops sth went wrong.
The idea is to keep it simple, they don't need to see all the error messages. Just add a primary action to retry or go back etc.
The GitHub approach for handling API errors is the best. They display a 404 page not only for 'not found' errors but also for cases like unauthorized, forbidden, etc. The point here is that the user does not need to know if the page exists if he/she does not have access to it.
I'm really not sure if we always need to add a 'retry' or 'go back' option when the main interface is not blocked and the navigation menu or other links are still accessible.
Depends on the context. If a user is not authorized to perform an action, it's better to explain why (they need to contact an admin, they need to upgrade their plan) rather than just giving them a Not Found error.
This article is really helpful! I've seen these minor mistakes in so many apps, and they truly make a big difference in the overall user experience. As developers, we often focus on functionality and forget how essential these UI details are. These tips are a great reminder of how much impact thoughtful design can have—definitely something we shouldn't overlook!
Indeed!
As a backend developer I say: I was searching for silver and found gold!
Thanks. That is a lot of thing that never crossed my mind.
I am glad that you found it useful 🙂
Great insights
Very helpful
Thanks! It's very usefull!
🙌🏼
Those are very basic and yet super useful recommendations. Thank you!