This section talks about best practices when it comes to designing your application.
The very first thing you need to do when starting the design of your application is to figure out the rules of the game, the system that you'll use for your design. You can create your own or avoid reinventing the wheel and pick one that someone has already made, such as Material made by the good folks at Google or our very own Canvas, made specifically for Bubble.
Having a system and especially creating one from scratch can take more time upfront but there are 2 main benefits to why you should do so:
- 1.It's much easier to design that way. You don't have to think about where you're putting each element on your page, which font to use, etc. You just follow the system with each new page/group/element.
- 2.Your app will look a lot better and will be easier to use. People respond well to consistency and will have a much better experience if your layouts, colors, sizes, spacing, etc. don't vary greatly across the application.
For figuring out your layouts, you may have to think on a couple of different levels.
You should figure out what the general structure of your pages will be like. You may end up with a single layout or several different ones.
Sample page layout
Here are the rules of the page layout:
- There is a floating header at the top of the page
- There is a navigation bar at the left side of the page, to switch between different sections
- There are two levels of navigation, top level and bottom level (which appears when a top level is opened for some of the top menu options)
- The navigation bar disappears at a certain width and can be opened through an icon in the top left corner
- The content of each section goes on the right side of the page
These should be used to actually displaying content within your page layouts. You'll probably have more of them than of the page layouts.
Sample group layout
Here are the rules of this layout:
- The title of the section is on the top left
- There is an action button (generally used for creating a new thing) on the top right
- Each line has a clickable title and a non-clickable description
- Each line has two icons - one that takes a primary action itself (the pencil icon) and the other one which exposes a vertical menu of secondary actions
Making application fully-responsive and working well at every screen width is one of the hardest things to do in Bubble but one that is critical to not making your users upset. A key component to doing that is creating layouts that scale vertically and not horizontally.
What does that mean? Basically, when creating a layout, think of what will happen when you need to add more stuff to it and when the screen becomes more narrow. Let's say you're creating a layout for a very simple row in a list with 2 action buttons, edit and delete. You may come up with something like this:
A button layout that scales horizontally
But what happens if the screen gets more narrow? Perhaps you can still fit the name and two buttons on a phone screen but what about when you need to add a third button? A better and more scalable alternative is one where you add buttons vertically, instead of horizontally:
A button layout that scales vertically
There is not much to say here, except for that having white/empty space in your application can be very effective in making the application feel uncluttered and clean.
Look at all that "wasted" space
You should make sure that every element that you use (or at least almost every element) is using a Style instead of having its visual properties on the element itself. This ensures the following:
- 1.That you're forced to keep your elements consistent and thus pleasing to the end user
- 2.That, if you ever decide to change the look and feel of your application, you won't have to hunt down individual elements and will instead be able to update multiple at a time
- 3.That your application is slightly smaller in size (this probably won't matter for most apps but if you have thousands of elements, the extra code required to store the visual properties on each element can really add up).
At the same time, you should ensure that you don't have too many styles because then they will be difficult to manage and also result in inconsistent UI. Somewhere in the 5-10 range is probably right for most element types (some may require fewer, some more).
What to do if you need to have an element that's styled in a one-off way? For example, let's imagine that you have an existing text style that you need to make bold in a single place. Do you create a whole separate style for that? We generally don't, instead we use a hack where we conditionally set the font to be bold and make the condition apply all the time. Below is an example.
The condition is always true and thus the text is always bold
The Style tab doesn't ensure that the sizes of your elements and padding are consistent, so you have to take care of that separately. Here are a few sample conventions that we use in Canvas:
- Pages have a width of 1220px
- Primary content goes into a group that's 860px wide
- Each primary content block is 780px wide
- Small buttons are 25px high, big buttons are 40px high
- There are 15px of spacing between each input
As you're designing and laying out your application, there are some high-level decisions that you'll need to make.
You'll have to decide whether you'll build a separate page for each of your screens or whether you put them on the same page, in hidden groups that show at the right time. Here's a table that compares the two methods on multiple dimensions:
Where we've landed with Canvas is that we use both separate pages as well as multiple groups on a page, depending on the use case. Let's imagine a very basic social networking application with the following functionality:
- Users can search for other users and view their profiles
- Users can add other users as friends
- Users can message their friends
- Users can update their profile and settings
We would probably use the following pages:
- Search page - this would be a standalone page where the user will search for other users and view the results in a list.
- Profile page - this would be a standalone page that will show information about a particular user.
- Dashboard page - this would be a page with several hidden groups that will be used to approve friend requests, message other users, and update profile/settings.
If you decide to have multiple groups on a page, you shouldn't stack them in an overlapping way on top of each other because the page height will then have to be as tall as the tallest group and you might end up with unnecessary empty space at the bottom. Instead, stack them vertically, one below the other one, and set each one to collapse when hidden. Also, you should make them all invisible by default and only visible when they need to be (vs. the opposite, which will result in a choppy experience).
Generally, reuseable elements are great. They fit well within our principle of modularity and allow us to easily add repeated functionality without needing to duplicate it. There is, however, a relatively large BUT, which is:
It's relatively hard to pass data to and from resueable elements
Each reuseable element accepts an object or a simple value and each custom workflow within a reuseable also accepts an object or a simple value. The hard part starts when you need to either pass more than 2 parameters to the reuseable element or you need to reference the result of something that happens within the reuseable element. There are three non-ideal ways to do that:
- 1.(Most likely a bad idea) Set fields on the
Current Userto pass data back and forth
- 2.Set states on the reuseable elements and reference them in either direction (either from page to reuseable or from reuseable to page)
- 3.Update the URL parameters and refer to those in either direction
- 4.Use one of the global variable plugins
#1 is probably a bad idea because multiple people won't be able to use the same user account at once. And #2-#4 are all doable but require a bit more work than not using reuseables.
Now that we've caveated reuseable elements, let's reiterate that you should probably be using them, especially if you're building functionality that will need to be accessed in multiple places and doesn't require passing a lot of data back and forth. A great example is a popup for editing an object - it only needs one parameter, which is the object itself and is most likely needed in multiple places (in the dashboard of the user who creates the object, in the dashboard of the app's owner, etc.).