Archive | CSS RSS for this section

Fixing the Width of a Select 2 with a Long Value in a Bootstrap Form Group or Input Group

If you have a Select2 control within a form-group or input-group div in a Bootstrap UI, a long value can cause the Select2 to grow to become wider than its container. In this post, I’ll show how to fix the issue.

The Problem with Large Values

In this demo, I have a form with two columns of fields, each within a well (which makes the container size very clear).

Select2 Long Values - A

In one field, there is a very long value. This usually isn’t an issue when you have explicit control over the options, but if you have an application where a drop-down box’s choices come from a plain text field on other documents, it’s possible.

Select2 Long Values - B

When I select the long value, it limits the amount of text displayed in the box to what will fit on one line, but it expands the size of the Select2 outside of its container.

Select2 Long Values - C

If I remove the second column of fields and re-test, it looks like the Select2 was enlarged to be the same the size as the parent container, which is too big for the area that it’s supposed to be in.

Select2 Long Values - C2

Fixing with CSS

This is a known issue with Select2 inside of a form-group or input-group within Bootstrap.

Fortunately, there’s a simple CSS fix, adapted from this post on github

.form-group .select2-container {
  position: relative;
  z-index: 2;
  float: left;
  width: 100%;
  margin-bottom: 0;
  display: table;
  table-layout: fixed;
}

If you’re using an input-group instead of a form-group, then change the first line to this:

.input-group .select2-container {

Select2 Long Values - D

Advertisements

Updating Select2 Styling to Match Bootstrap Fields

Select2 is an awesome jQuery plugin to enhance the functionality of combo boxes. But if you implement it in an application with a Bootstrap UI, you’ll notice that the styling is not consistent. In this post, I’ll show how to make the styling of Select2 fields consistent with other fields on the form.

Bootstrap Default Styling

Here’s an example of a simple Bootstrap form, including two combo box fields. The styling is very consistent across all of the fields.

Select2 A - Default Drop-Down

Select2 Default Styling

Once I implement Select2 and add the code to initialize combo boxes as Select2 fields, they styling changes. The width and internal padding and line spacing are not consistent with other bootstrap fields. (Click image to enlarge in order to see the difference more clearly.)

Select2 B - Default Select2 Style

Consistent Styling

Fortunately, by inspecting a standard bootstrap field either in the bootstrap CSS or in the browser’s developer tools, I can see the styles in use and replicate them for a more consistent look.

Select2 C - Consistent Select2 Style

Here is the CSS required to make it happen:

.select2-container {
  width:100%;	
}

.select2-container a.select2-choice {
  font-size: 14px;
  height: 38px;
  padding: 8px 12px;
  line-height: 1.42857;
}

.select2-container .select2-choice .select2-arrow {
  padding-top:6px;
}

The first rule makes the field width use 100% of the size of its container, as bootstrap fields do.

The second set of rules sets the font and field styling to make them consistent.

The third rule vertically centers the drop-down arrow for the larger field.

XPages Tip: Displaying View Panel Sort Icons on a Separate Line

If there isn’t enough room to display both the column title and sort icons in all column headers in a view panel, you can end up with an uneven look. In this post, I’ll show how to use CSS to move the sort icons down to a new line.

Column Header Layout

If you’re using a view panel with sortable columns, you will ideally not have too many columns and instead have enough screen real estate that the sort icons don’t make a difference.

View Panel Sort Icons - 1

However, a common scenario is that there are a lot more columns crammed in and some (but not all) sort icons wrap to a new line. This ends up causing an uneven look.

View Panel Sort Icons - 2

In addition, the icons take up space, so you may have columns that have a 1- or 2-letter code, but the sort icon makes the column 2-3 times wider than it needs to be, so you lose precious real estate.

If that happens and you’d like to make them consistent, you can use CSS to always move the sort icons to the next line.

Column Header Source

In order to apply CSS to adjust the layout, we need to view the page source to see what’s being generated.

This snippet contains the tags that start the view panel (line 1), start the column header row (lines 2-3), and display the first column header (lines 4-16).

<table id="view:_id1:viewPanel1" class="xspDataTable">
  <thead>
    <tr>
      <th scope="col">
        <div class="xspPanelViewColumnHeader">
          <span>
            <a id="view:_id1:viewPanel1:viewColumn1:__internal_header_title_id" href="#" class="xspPanelViewColumnHeader">
              <span class="xspPanelViewColumnHeader">Group</span>
            </a>
          </span>
          <span>
            <img id="view:_id1:viewPanel1:viewColumn1:__internal_header_sort_icon" src="/domjava/xsp/theme/common/images/sort_none.gif" 
alt="Sort Toggle" title="Sort Toggle" class="xspImageViewColumnHeaderSort">
          </span>
        </div>
      </th>

This shows that a column header div contains a span with the column title and another span with the sort icon.

Adding a New Line with CSS

This gives us enough information to know how to target the proper element with CSS. There are several ways to go about it. My example will target the table (with class name), div (with class name), and then get the first span tag. It will add the new line after the first span.

table.xspDataTable div.xspPanelViewColumnHeader span:first-of-type:after {
  content: '\A';
  white-space: pre;
}

The '\A' in the content attribute denotes a new line with CSS. It does not work to put a <br> tag there. The white-space attribute is also required or you may not see any difference.

Now, all of the sort icons appear on a separate line.

View Panel Sort Icons - 3

You can tweak it by adjusting the space between the lines or centering, etc, but this gets the ball rolling.

Also, if you want to modify the images themselves, you can target .xspImageViewColumnHeaderSort with CSS.

CSS Tip: Dealing with Table Spacing in IE Compatibility Mode

One of the most frustrating things about dealing with IE compatibility mode is how it handles table layouts. In my recent experience, it seems to automatically stretch them out to take up more room than you’d expect. It seems to generally disregard padding, spacing, and column width CSS settings (unless the column width is greater than the amount of space the browser wants to provide for a column).

Even worse, it doesn’t always space the columns evenly. In a recent application, cells with consistent content were sized differently in compatibility mode, so the content of some cells would wrap and others wouldn’t — even though there would have been plenty of space for all of the data if the columns had been spaced evenly.

Since the pattern seems to be that it will stretch tables out to the full available width, the quick workaround to improve table layouts in compatibility mode is to put a container around the table (such as a div) and use CSS to fix the width of that container. This doesn’t cause it to space the columns perfectly, but it can be very handy in limiting the size of the table as needed.

XPages Tip: Dynamically Loading a Style Sheet for IE Compatibility Mode

I’ve wrestled with IE’s compatibility mode (which makes higher versions of IE act like IE7) a few times recently. Some workarounds I’ve come across were documented previously. In this post, I’ll show how to conditionally load a style sheet that has styles specifically for compatibility mode.

Themes to the Rescue

Fortunately, you can determine the browser and version in XPages and you can use a theme to conditionally load a style sheet based on the browser and version.

The snippet below will load one style sheet if the browser is IE7 (or below) and load another style sheet if the browser is anything else.

The .isIE(0,7) method returns true or false based on whether the current browser is any version of IE from 0 to 7.

<resource rendered="#{javascript:context.getUserAgent().isIE(0,7)}">
  <content-type>text/css</content-type>
  <href>IE7StyleSheet.css</href>
</resource>
	
<resource rendered="#{javascript:!context.getUserAgent().isIE(0,7)}">
  <content-type>text/css</content-type>
  <href>NonIE7StyleSheet.css</href>
</resource>

It’s a massive headache to deal with compatibility mode, but this flexibility makes it a little easier to adjust styles as needed.

CSS Tip: Selecting an Element that has Two Classes

If you’re familiar with CSS, you know that you define the style for an element with a specific class by referencing .className{ } in a style sheet and you’re familiar with the hierarchy of selectors, but did you know that there’s a selector that looks for an element with two classes?

Here’s an example page with three div tags. The first one has class1, the second one has class2 and the third one has both class1 and class2.

<div class="class1">This is div 1</div>
<div class="class2">This is div 2</div>
<div class="class1 class2">This is div 3</div>

Here’s a simple style sheet that, when included on the page, will set the font color of class1 and class2:

.class1 {
color:#FF0000;
}

.class2 {
color:#00FF00;
}

Here is the result:
TwoClasses_1

The first div gets the red font because it has class1 assigned. The second div gets the green font because it has class2 assigned. The third div also gets the green font because class2 is the last class assigned to it, so it picks up the style from that class (when it conflicts with any style set by the first class).

Now, let’s say I want to make the third div’s font blue (without changing the style of the first two). I can’t change the class1 or class2 styles because that will change one of the other divs.

Fortunately, there’s a CSS selector that allows you to specify a style that applies to an element that has two classes. Just specify them as .class1.class2 with no space between the two class names.

This css entry will do the trick in the sample shown above:

.class1.class2 {
color:#0000FF;
}

This uniquely identifies the third div because it has both of those classes.

TwoClasses_2

Of course, this is an overly simplistic example, but I’ve had a few cases recently where this was helpful when working with objects that have multiple class names assigned by XPages and dojo.

Runtime optimized JavaScript and CSS resources – some results

In Notes/Domino 8.5.3, there is a new setting on the XPages tab of the Application Properties called Use runtime optimized JavaScript and CSS resources.

Runtime Optimized JS

Methodology

I put it to the test on two applications and loaded several pages 5 times each and, using firebug (on the Net tab), noted the amount of data loaded and the load time.

Firebug_Net

Results

In the first database, I opened a page with a view panel and a page with a similar view panel, but a full-text search executed against it. I also opened a page with a document in edit mode and a page with a document in read mode.

This database uses several dojo components (in edit mode of the form), a dojo tabbed table on the form, and some dojo logic around the page with the view panel. It has a few small stylesheets, but uses the OneUI application layout, so there are plenty of stylesheets involved.

Database 1

Without Optimization With Optimization
Page Size Load Time Size Load Time
View 21k 1.78s 7k 0.96s
View-Search 7.5k 1.38s 7.3k 1.12s
Document-Edit 13.7k 2.33s 6.7k 1.47s
Document-Read 11.4k 1.18s 4.5k 0.99s

There are significant improvements in the size of the files loaded and the loading performance.

In the second database, I tested with a page loading an ExtJS grid, so it uses grid libraries and stylesheets, along with jQuery. The database also uses the OneUIv2.1 theme.

Database 2

Without Optimization With Optimization
Page Size Load Time Size Load Time
ExtJS Grid 3.2m 3.02s 3.2m 3.15s

It changed the total number of GET requests on the page from 38 to 33.

A Better Understanding

Initially, I was surprised that it didn’t make a noticeable difference in the second database, so I looked into it further and found that it is intended to improve the loading of dojo modules. It is not going to help with any external javascript libraries that you include in your application. (Quite frankly, they should already be optimized for you.)

Here’s how the What’s new in Domino Designer 8.5.3 page in the DDE help file describes it:

For performance reasons, the XPages runtime now features a new option that dynamically aggregates multiple Dojo modules, or multiple CSSs into a single file. This results in the following performance improvements:

  • a decrease in requests sent from the browser to the server
  • an increase in user performance, particularly in the context of networks with high latency
  • an increase in the speed of JS/CSS parsing from the browser
  • the freeing up of server connections to fulfill other requests

As an extreme example of the saving, let’s say the XPages Extension Library is using the page DWA_ListView.xsp. Without the aggregator enabled, 82 requests are made to the server. With the aggregator enabled, the count decreases to 6 requests, including the Ajax request that gets the data. Also, a test run on processing time might see changes from ~4 sec to ~800 ms.

Your results?

Of course, your mileage may vary. I see that Julian Buss had impressive results with a test, but I haven’t seen a lot documented.

If you’ve tested this out, what kind of results have you seen?