Creating buttons with a three-dimensional (3D) or Neumorphism Button effect can make your app’s user interface more engaging and immersive. One popular design trend that achieves this effect is Neumorphism, which uses soft shadows and gradients to create a realistic, tactile appearance. In this article, we’ll explore how to create a 3D button in Flutter using Neumorphism so that you can add depth and interactivity to your app’s buttons.
What is Neumorphism?
Neumorphism is a modern design trend that seeks to create a 3D effect on flat surfaces, such as buttons or cards, by using soft shadows and gradients. It’s a minimalist design approach that emphasizes simplicity and a sense of realism. The overall goal of Neumorphism is to make user interface elements look and feel more tangible and lifelike as if they’re popping out of the screen.
To achieve this effect, Neumorphism typically employs a combination of inner shadows, highlights, and outer shadows to create the illusion of depth. The color palette is often muted and subdued, to avoid distracting from the depth effect. The result is a user interface that feels natural and tactile, inviting users to interact with the app in a more intuitive way.
In the context of creating a 3D button in Flutter, Neumorphism can be a powerful tool for adding depth and interactivity to your button design. By using soft shadows and gradients to create a realistic, tactile appearance, you can create a button that users will want to click on again and again
Important Color Criteria for Neumorphism Button
To create a Neumorphism design, it’s important to use colors that match the background color of the user interface element. This is because Neumorphism relies on shadows to create depth, and the shadows must blend seamlessly with the background to achieve a natural appearance.
In Neumorphism design, shadows are used to create a subtle 3D effect. A dark shadow is applied to one side of the element, while a lighter color is applied to the opposite side. The darker shadow gives the appearance of a recessed area, while the lighter color creates the illusion of a raised surface. The combination of the two creates the overall 3D effect.
Complete Guide: Implementing a Neumorphic Button in Flutter
- First, create the basic skeleton of a Stateful widget called “NeumorphismButton”.
class NeumorphismButton extends StatefulWidget {
const NeumorphismButton({Key? key}) : super(key: key);
@override
State<NeumorphismButton> createState() => _NeumorphismButtonState();
}
class _NeumorphismButtonState extends State<NeumorphismButton> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white70,
appBar: AppBar(),
body: Center( ),
);
}
}
- Inside the
Center
widget, we will add aContainer
widget that will serve as our Neumorphism button.
Center(
child: Container(
// Add rounded corners to the container
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
// Use the same color as the background for your user interface element when applying the Neumorphism design style
color: Colors.white70,
// Apply two box shadows to create the Neumorphism effect
boxShadow: [
// Apply a brighter soft shadow in the top left corner
BoxShadow(
blurRadius: 30,
offset: Offset(-20,-20),
color: Colors.white,
),
// Apply a darker soft shadow in the bottom right corner
BoxShadow(
blurRadius: 30,
offset: Offset(20,-20),
color: Colors.grey,
)
]
),
child: SizedBox(
height: 200,
width: 200,
),
),
)

- To make your container more dynamic when using the Neumorphism design style, you can utilize the ‘inset box shadow’ property in the inner shadow
First, you’ll need to add the package(flutter_inset_box_shadow: ^1.0.8) to your project’s dependencies by adding it to your ‘pubspec.yaml’ file. You can find the latest version of the package on the package’s page on the pub.dev website.
After adding the package to your ‘pubspec.yaml’ file, you’ll need to run ‘pub get’ to download the package and its dependencies. Once the package is downloaded, you can then import it into your main file using the import statement.
flutter_inset_box_shadow: ^1.0.8
Once you’ve imported the package, you can use the ‘BoxDecoration’ class to create a box with an inset shadow. The ‘BoxDecoration’ class provides many properties for customizing the look of the box, including the ‘boxShadow’ property for setting the shadow.
import 'package:flutter/material.dart' hide BoxDecoration, BoxShadow;
import 'package:flutter_inset_box_shadow/flutter_inset_box_shadow.dart';
To create an inset shadow, you’ll need to set the ‘spreadRadius’ property to a negative value. This will cause the shadow to appear inside the box instead of outside. You can also adjust the ‘blurRadius’, ‘offset’, and ‘color’ properties to customize the look of the shadow.
boxShadow: [
BoxShadow(
blurRadius: 30,
offset: Offset(-20,-20),
color: Colors.white,
inset: true, ///set value to true
),
BoxShadow(
blurRadius: 30,
offset: Offset(20,-20),
color: Colors.grey,
inset: true, ///set value to true
)
]

- To create a button from a container with the Neumorphism design style in Flutter, we can wrap our container with a ‘GestureDetector’. To make the button more interactive, we can set the initial value of ‘isPressed’ to true. To create a more dynamic effect, we can change the offset and blur properties of the button’s shadow when the user interacts with it.
bool isPressed = true;///intially the set the isPressed true
Set the background color for the button and Set the distance and blur properties for the shadow based on whether the button is pressed or not
///Set the background color for the button
final backgroundColor = Colors.white70;
///Set the distance and blur properties for the shadow based on whether the button is pressed or not
Offset distance = isPressed?Offset(10,10):Offset(20,20);
double blur = isPressed?5.0:30.0;
- To update the button state when the user taps on it, we can wrap our container with a ‘GestureDetector’ widget and add an ‘onTap’ function. Inside the ‘onTap’ function, we can use ‘setState’ to change the state of the button based on whether it is pressed or not.
onTap: (){
setState(() {
isPressed = !isPressed;
});
},
- To create an interactive button with a dynamic shadow effect, we can change the properties of the button based on the user’s interaction. For example, when the user presses the button, we can increase the shadow blur and distance to make the button appear more 3D. Similarly, when the user releases the button, we can decrease the shadow blur and distance to make the button appear less 3D. We can achieve this effect by changing the values of the ‘blur’, ‘distance’, and ‘isPressed’ properties inside the ‘onTap’ function.
GestureDetector(
// Toggle isPressed on tap
onTap: (){
setState(() {
isPressed = !isPressed;
});
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 600), // Adding duration for smooth transition
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: isDarkMode?const Color(0xff2e3239):backgroundColor, // Setting background color based on isDarkMode and backgroundColor variable
boxShadow: [
BoxShadow(
blurRadius: blur, // Changing blur as per isPressed
offset: -distance, // Changing offset as per isPressed
color: isDarkMode?const Color(0xff35393f):Colors.white,
inset: isPressed, // If isPressed is true, inner shadow will display
),
BoxShadow(
blurRadius: blur, // Changing blur as per isPressed
offset: distance, // Changing offset as per isPressed
color: isDarkMode?const Color(0xff23262a):Colors.grey,
inset: isPressed, // If isPressed is true, inner shadow will display
)
]
),
child: SizedBox(
height: 200,
width: 200,
child: Padding(
padding: const EdgeInsets.all(30.0),
child: Image.asset("assets/images/sitejuggler.png"),
),
),
),
),
),
Full Source Code
import 'package:flutter/material.dart' hide BoxDecoration, BoxShadow;
import 'package:flutter_inset_box_shadow/flutter_inset_box_shadow.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context){
return const MaterialApp(
home: NeumorphismButton(),
);
}
}
class NeumorphismButton extends StatefulWidget {
const NeumorphismButton({Key? key}) : super(key: key);
@override
State<NeumorphismButton> createState() => _NeumorphismButtonState();
}
class _NeumorphismButtonState extends State<NeumorphismButton> {
bool isPressed = true;
bool isDarkMode = true;
@override
Widget build(BuildContext context) {
const backgroundColor = Colors.white70;
Offset distance = isPressed?const Offset(10,10):const Offset(20,20);
double blur = isPressed?5.0:20.0;
return Scaffold(
backgroundColor: isDarkMode?const Color(0xff2e3239):backgroundColor,
appBar: AppBar(),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: (){
setState(() {
isPressed = !isPressed;
});
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 600),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: isDarkMode?const Color(0xff2e3239):backgroundColor,
boxShadow: [
BoxShadow(
blurRadius: blur,
offset: -distance,
color: isDarkMode?const Color(0xff35393f):Colors.white,
inset: isPressed,
),
BoxShadow(
blurRadius: blur,
offset: distance,
color: isDarkMode?const Color(0xff23262a):Colors.grey,
inset: isPressed,
)
]
),
child: SizedBox(
height: 200,
width: 200,
child: Padding(
padding: const EdgeInsets.all(30.0),
child: Image.asset("assets/images/sitejuggler.png"),
),
),
),
),
),
const SizedBox(
height: 50,
),
TextButton(onPressed: (){
setState((){
isDarkMode =!isDarkMode;
});
}, child: isDarkMode?const Text("Change to light mode",style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.normal,
color: backgroundColor
),):const Text("Change to Dark Mode",style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.normal,
color: Color(0xff2e3239))))
],
),
),
);
}
}
Output: Neumorphism Button
In this project, we created a simple Flutter application that showcases the Neumorphism design style. The application features a button that changes colors when pressed, a toggle switch for switching between light and dark modes, and a Neumorphism button.
The Neumorphism button is implemented using a Container widget that has a BoxDecoration with a border-radius and two BoxShadow widgets. One BoxShadow is a lighter soft shadow, and the other is a darker soft shadow. These shadows are offset in opposite directions to create the Neumorphism effect.
The button changes color when pressed, and the toggle switch allows the user to switch between light and dark modes. The Neumorphism button adjusts its colors accordingly to maintain the visual consistency of the application.
Overall, this project demonstrates how to create a user interface element that uses the Neumorphism design style, and how to integrate it into a larger Flutter application.
Conclusion
Neumorphism is a design trend that creates a 3D effect on flat surfaces using soft shadows and gradients, and is often referred to as “soft UI” or “new skeuomorphism.” To create 3D button animations in Flutter using this trend, use the inset_box_shadow
package and adjust properties such as offset and blur to create a dynamic container. Wrap the container with a GestureDetector
widget and change properties like a blur and offset on tap for a more interactive experience.