X

Geertjan's Blog

  • April 26, 2016

Flexbox and Oracle JET (Part 2)

Geertjan Wielenga
Product Manager

Following on from part 1, we're going to look at the CSS classes "oj-flex" and "oj-flex-item".

Here is the official documentation where you will see these CSS classes defined:

http://www.oracle.com/webfolder/technetwork/jet/stylingdoc.html

Also, the JET Developer's Guide also contains additional information about Oracle JET's flex layout and grid systems in the Designing Responsive Applications chapter at:

http://docs.oracle.com/middleware/jet201/jet/developer/GUID-67956274-4056-4D54-8BC7-18942DA7338A.htm#JETDG263

You might find the topics describing Oracle JET's use of media queries, flex layouts, and the grid system helpful in the above chapter.  

Spot "oj-flex" and "oj-flex-item" in the screenshot below, which is a slightly tweaked part of "index.html" in the "Oracle JET Quick Start Basic":

Here, in bold, is where they are: 

<div class="oj-web-applayout-max-width oj-web-applayout-content">
<div class="oj-flex">
<div class="oj-lg-9 oj-sm-12 oj-flex-item oj-flex">
<div id="mainContent" role="main" class="oj-panel oj-margin oj-flex-item"
data-bind="ojModule: router.moduleConfig">
</div>
</div>
<div class="oj-lg-3 oj-sm-12 oj-flex-item">
<div id="complementaryContent" role="complementary" class="oj-panel oj-margin oj-flex-item"
data-bind="ojModule: {viewName: 'compContent'}">
</div>
</div>
</div>
</div>

Now that you have spotted the places where "oj-flex" and "oj-flex-item" are used, let's hone in on one specific section, shown in bold below:

<div class="oj-web-applayout-max-width oj-web-applayout-content">
<div class="oj-flex"><div class="oj-lg-9 oj-sm-12 oj-flex-item oj-flex">
<div id="mainContent" role="main" class="oj-panel oj-margin oj-flex-item"
data-bind="ojModule: router.moduleConfig">
</div>
</div>

<div class="oj-lg-3 oj-sm-12 oj-flex-item">
<div id="complementaryContent" role="complementary" class="oj-panel oj-margin oj-flex-item"
data-bind="ojModule: {viewName: 'compContent'}">
</div>
</div>
</div> 
</div> 

The above segment in bold is the place where the main content will be found. In the first line in bold above, notice the "oj-flex", which is set on the "div" that the main content modules will be put into. Anytime you have a container, inside that container you can nest in items. If you want to make something not only be an item within a container, via "oj-flex-item", but the start of a new container, then just add "oj-flex" along with "oj-flex-item".

Let's now take the view of the "people" module, i.e., "people.html", to experiment with "oj-flex" and "oj-flex-item". Go to people.html" and let's build something up from scratch. The first thing to think about is: "How many rows do I want?" If you think about rows first, or about how many vertical containers, that's the best way to start working with Flex Layout. Then, you can adjust items inside of those rows, i.e., these are the Flexbox containers, as you go along.

In "people.html", let's start simply like this:

<h1>People Layout</h1>
<div class="oj-flex-item">
</div>

Right now, what we've got is one "div", which has been set as an "oj-flex-item". It has nothing in it and you can't tell that it's there when you look in the page, which will just be blank, aside from the "h1" content. A good tip when doing layouting with Flex Layout, i.e., at least during development, is to add an "oj-panel":

<h1>People Layout</h1>
<div class="oj-flex-item oj-panel">
</div> 

In the browser, you now see a little border, and you can tell where things are at, roughly:

Therefore, the "oj-panel" is very useful when laying things out, to see where the containers and items are fitting within the page, regardless of whether you ultimately want to use "oj-panel" in the actual release of your product. It enables you to see what the padding is, while you can also use different colors in the background by using different alternate panels, too.

If that is our first row, let's put that in there: 

<h1>People Layout</h1>
<div class="oj-flex-item oj-panel"> 
first row
</div>

Of course, the above will have this result:

Then copy that and put in a few of them, as follows: 

<h1>People Layout</h1>
<div class="oj-flex-item oj-panel">
first row
</div>
<div class="oj-flex-item oj-panel">
second row
</div>
<div class="oj-flex-item oj-panel">
third row
</div>

From this point, let's just focus on the rendering of the "people.html", i.e., in this screenshot that's all you see, without all the content around it:

As you can see, the items are stacking up, they're looking OK, though they definitely don't have the padding around them that we would like, according to the Oracle Alta UI. Let's add a margin to each item, as follows:

<h1>People Layout</h1>
<div class="oj-flex-item oj-panel oj-margin">
first row
</div>
<div class="oj-flex-item oj-panel oj-margin">
second row
</div>
<div class="oj-flex-item oj-panel oj-margin">
third row
</div>

Now we have some padding in there:

That's the default that "oj-margin" gives us, from the Oracle Alta UI spec. Rather than overriding it, if needed, the better approach is to create your own CSS margin class, since the various Oracle JET components also make use of "oj-margin" and hence if you change "oj-margin" itself, you may end up with unintended side effects.

Where we are now is that we have three "oj-flex-items", which are all contained by the "oj-flex" container in "index.html". Now, let's say that in the second row, i.e., the second "oj-flex-item", we want to put three or four other items:

Getting to the above point is as simple as nesting new "oj-flex-items", like this, i.e., below, only the items in bold have been added: 

<h1>People Layout</h1>
<div class="oj-flex-item oj-panel oj-margin">
first row
</div>
<div class="oj-flex-item oj-panel oj-margin"><div class="oj-flex-item oj-panel oj-margin">
2 - 1
</div>
<div class="oj-flex-item oj-panel oj-margin">
2 - 2
</div>
<div class="oj-flex-item oj-panel oj-margin">
2 - 3
</div>
<div class="oj-flex-item oj-panel oj-margin">
2 - 4
</div>

</div>
<div class="oj-flex-item oj-panel oj-margin">
third row
</div>

However, probably you don't need that whole border along the outside of the second level items. And maybe you want them to be side-by-side, instead. Right now, we have an "oj-flex-item", which contains other instances of "oj-flex-item". Since they're all "items", they're still children of the "container" item in the "index.html" page. Really, what you would like is for the second level items to be items for the "div" element that contains them. Therefore, let's add in an "oj-flex", which will turn that "div" element into a container:

<div class="oj-flex oj-flex-item oj-panel oj-margin">
<div class="oj-flex-item oj-panel oj-margin">
2 - 1
</div>
<div class="oj-flex-item oj-panel oj-margin">
2 - 2
</div>
<div class="oj-flex-item oj-panel oj-margin">
2 - 3
</div>
<div class="oj-flex-item oj-panel oj-margin">
2 - 4
</div>
</div>

The above is the only change I have made and now I have the following layout:

Once you set a "div" as being a container, you enable it to control its own content. By default, containers flow in a row, as you can see above. The "flex-direction" property is, by default, set to "row". You can set that to "column", instead, as will be shown later in this article, as well as "reverse row" and "reverse column". The reverse classes probably might mess things up for RTL languages, which Oracle JET automatically incorporates. You can also mess with the order, overriding the DOM order, which might cause conflicts with accessibility requirements and RTL language support, though. Be aware that this flexibility exists, if needed, as well as the problems that might occur.

If you remove "oj-panel" and "oj-margin" from that "div" element, you will have a layout like this:

The inner items are now all in a row, without a panel around them. Once you set up a container, by default, the items inside it are going to resize to fit the container. So, if you remove one of the inner items, in "people.html", you will automatically have the resize effect and the result will be as follows:

Automatically, the inner items stretch across and take up the space in order to position the three items equally.

Let's now go a step further and add inner items to the third "div", after making that "div" a container, while removing its panel and margin. We'll also put back the fourth inner item in the second "div", as a starting point:

<h1>People Layout</h1>
<div class="oj-flex-item oj-panel oj-margin">
first row
</div>
<div class="oj-flex oj-flex-item">
<div class="oj-flex-item oj-panel oj-margin">
2 - 1
</div>
<div class="oj-flex-item oj-panel oj-margin">
2 - 2
</div>
<div class="oj-flex-item oj-panel oj-margin">
2 - 3
</div>
<div class="oj-flex-item oj-panel oj-margin">
2 - 4
</div>
</div>
<div class="oj-flex oj-flex-item">
<div class="oj-flex-item oj-panel oj-margin">
3 - 1
</div>
<div class="oj-flex-item oj-panel oj-margin">
3 - 2
</div>
</div>

The result is as follows:

There are now 4 columns in the middle and 2 across the bottom. As you resize this, the rows are maintained, becoming smaller and smaller as you make the browser smaller:

However, let's say that we want the items in the second row to stack as we move smaller, i.e., as we get to a phone-size resolution. Since items inherit from their container, we'll use the "flex-direction" property, mentioned earlier, to switch from the default "row" direction to "column", when the resolution is "small", i.e., on mobile devices. Take note of the addition below, in bold:

<div class="oj-sm-flex-direction-column oj-flex oj-flex-item">
<div class="oj-flex-item oj-panel oj-margin">
2 - 1
</div>
<div class="oj-flex-item oj-panel oj-margin">
2 - 2
</div>
<div class="oj-flex-item oj-panel oj-margin">
2 - 3
</div>
<div class="oj-flex-item oj-panel oj-margin">
2 - 4
</div>
</div>

The above causes a problem immediately because even when you're not in a small resolution, the rows are now columns, while we only wanted that for small resolutions. Be aware that when you use these resolution-related breakpoints, the related CSS classes work from whatever size you tell them on up. In this particular case, we're telling the items in a container to be small, and on up. When I look in my page, of course it's going to drop into a columnar layout, even on large and extra large.

If we only want the columnar direction on small, there are classes for small only, notice the difference below:

<div class="oj-sm-only-flex-direction-column oj-flex oj-flex-item"> 

And now, only when the resolution is small, will you see the columnar layout:

Also notice that the container below the one we've been working with is still making use of the default "row" direction.

More will come in the next part of this series, with an increasing focus on overriding default behavior, though the above should give a clear overview of the usage and advantages of Flexbox in Oracle JET. Many thanks to JB Brock for all the info above.

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha
Oracle

Integrated Cloud Applications & Platform Services