Archive for the 'CSS' Category

June 7th, 2022
8:49 am
PrimeNG Theming Strategy

Posted under Angular & CSS & Knowledge Base & PrimeNG
Tags

I have already noted here and here that Prime have removed themeroller support in favour of a paid for theme designer tool, and more significantly, have removed there actual new theme SCSS api from open source, so this is paid for as well, preventing you from using their new API with manually designed themes.

My solution is to pick one of the free themes which is nearest to the look I want, and then rebadge its compiled css (which you do get a copy of) as SCSS, and then customise that.

Obviously the raw CSS has a lot of duplication compared to the original SCSS. My original strategy was to copy raw rules to the end of the file in a new section, and modify them as required to override the original rules, by making more specific as required (e.g. by adding a p.component class). This would then allow them to be matched to their originals, which sounded attractive from a correlation/derivation point of view.

In the end I gave up on this idea. The section with the modified rules was getting messy with all the duplication, and was harder to make sense of. I therefore adopted a new strategy which was to copy all the rules and modify as required, and then do some fairly straightforward merging of them into single SCSS rules. This dramatically simplified the modifications and made them clearer to read, so I have stuck with this idea going forwards.

There have been oddball cases where I have taken a different approach, and actually edited the original generated css directly. For example, there is a media query to switch the menu bar into hamburger only mode at a certain fixed viewport width. I did not want this, so as the media query covered a lengthy section of css, I removed the media query directly, replacing it with a class based rule so I could still switch in hamburger mode dynamically when I wanted. This still encapsulated the same original css, and seemed the tidiest approach in this case.

Comments Off on PrimeNG Theming Strategy

May 26th, 2017
12:55 pm
Dynamically updating css classes on child components from a parent property

Posted under Angular & CSS & PrimeNG
Tags , , ,

I was using a button component to encapsulate the primeNG one, to allow it to responsively change to an icon only button at smaller screen widths. Whilst in theory I could have dynamically modified the internal primeNG button CSS, this was complex and I did not want  to become tightly coupled to it. My button component therefore simply selected one of 2 buttons via a media query, setting the unwanted one to display:none.

I wanted any classes added to the top level ss-button to be set on the underlying primeNG buttons. One use of these buttons was in a home brewed tab component, and  I was dynamically changing the button colour via ui-button-primary, ui-button-secondary so that the active tab had a ‘primary’ coloured button and the inactive ones were ‘secondary’ which caused them to become uncoloured ghost buttons – ideal for my requirement.

During refactoring to replace the ‘full size only’ primeNG buttons with the resizing ss-buttons I introduced a bug and the colour change failed to work. The initial (incorrect) refactored code was as follows:-

ss-tab-toolbar.component.html

<ng-container *ngFor="let tab of tabs">
<app-ss-button [label]="tab.label" [icon]="tab.icon" (click)="setActiveTab(tab)"
[ngClass]="{'ui-button-primary': isActiveTab(tab), 'ui-button-secondary': ! isActiveTab(tab)}"></app-ss-button>
</ng-container>

ss-button.component.html

<button pButton type="button" [title]="label" [label]="label" [icon]="icon" class="ss-button icon-text"
[ngClass]="class" ></button>
<button pButton type="button" [title]="label" [icon]="icon" class="ss-button icon-only"
[ngClass]="class" ></button>

ss-button.component.ts

@Component({
selector: 'app-ss-button',
templateUrl: './ss-button.component.html',
styleUrls: ['./ss-button.component.scss']
})
export class SSTabButtonComponent {

@Input() label: string;
@Input() icon: string;
@Input() class: string;

constructor() { }
}

The issue was that I was using [ngClass] dynamically to update the classes on the <app-ss-button> in ss-tab-toolbar.component. html. This used to work for the PrimeNG buttons, but now would have no effect as the classes need to be changed on the child buttons not the encapsulating parent. A simple change of [ngClass] to [class] fixed the problem, as the parent style change then updated the property on the parent component which was then picked up by the children correctly.

modified ss-tab-toolbar.component.html

<ng-container *ngFor="let tab of tabs">
<app-ss-button [label]="tab.label" [icon]="tab.icon" (click)="setActiveTab(tab)"
[class]="{'ui-button-primary': isActiveTab(tab), 'ui-button-secondary': ! isActiveTab(tab)}"></app-ss-button>
</ng-container>

Happily the dynamic nature of angular meant that this worked perfectly for tab changes – the change on the parent class was propagated correctly to the child and the button colours changed correctly.

I was wondering initially whether I would need to involve observables to make this work but this was not the case – this kind of dynamic propagation pattern is worth remembering in future.

No Comments »

May 18th, 2017
6:30 pm
Tricks with the PrimeNG Grid CSS Component

Posted under Angular & CSS & HTML & PrimeNG
Tags ,

Update 19/5/2017

I noticed that my original attempt below, whilst causing the text div to flow under the image div at smaller screen sizes, did not cause the text div to be full width when it was sitting underneath. To do this properly I needed to use a combination of 2 specific non-default (i.e. not ui-g-*) responsive style classes on the text div, in this case ui-md-9 and ui-sm-12. This causes the following:-

  1. At the u-md-* screen size boundary, and higher, the ui-md-9 kicks in and the image and text are on the same line.
  2. Below the ui-md-9 boundary, the ui-sm-12 kicks in and allows the text div to be full width. Without this, it would sit underneath but the default ui-g-9 would still be in effect so it would not switch to full width.

The modified code fragment for the item-text div is as follows:-

<div class="ui-g-9 ui-sm-12 ui-md-9 item-text">

Original Post

I did this quite by accident, due to adding an unwanted “>” on the end of a ui-g-3 class for the div around the left image in a data list – it caused the class to be ignored.

The code (with the offending character and the ui-g-3 class removed) is as follows:-

<ng-template let-place pTemplate="item">
<div class="ui-g list-item item-image">
<div class="item-image">
<img src={{place.thumbUrl}}>
</div>
<div class="ui-g-9 item-text">
<h4>{{place.shortLocation}}</h4>
<h3>{{place.name}}</h3>
<p>{{place.strapline}}</p>
</div>
</div>
</ng-template>

The scss for the component is here (note this is from the component scss file so is encapsulated by Angular from bleeding out):-

h3 {
font-size:1.1em;
font-weight: normal;
margin:.2em 0;
}
h4 {
font-size:1em;
font-weight: normal;
margin: 0;
}
p {
font-size:1em;
margin:.2em 0;
}
.list-item {
padding:.5em;
border-bottom:1px solid #D5D5D5;
display:flex;
align-items: center;
}
.list-item .item-image {
padding-right:1em;
}
.list-item .item-text {
padding-left:0;
}

The happy effect of this was that the image div did not have a ui-g-* class to size it, so had a fixed size determined by the thumbnail, and was not a floating div. When I used a ui-g-3 class for it by removing the offending “>”, then the gap between the image and the text increased as the width changed, which is not something I wanted – the fixed padding there due to the bug was fine for all screen widths.

The ui-g-9 class happily floated next to it and flowed underneath as required. Different ui-g-* classes such as ui-g-6 and ui-g-8 just caused the flow to happen at a different width point.

I could probably have achieved a similar effect by using a ui-g-3 class for the image as I had intended, and then explicitly fixing the width for that div (or e.g. setting a min-width and a max-width).

I may need to do this or re-jig it if I have to cater for different thumbnail sizes, but my preferences is to scale all thumbnails to the same size as it gives a much better layout.

Whether this trick technically breaks or violates the ui-g-* grid css rules I am not sure, the documentation on them is not hugely comprehensive, but I will ponder this one in due course.

For now it works fine!

No Comments »

May 18th, 2017
5:56 pm
Vertically Centering items in a div–2017 version!

Posted under Angular & CSS & PrimeNG & Web
Tags ,

I posted about this kind of issue back in 2010 here.

Nowadays for my own project work I am happy to assume recent browsers, in particularly IE11 at least (noting that even this has been out a while now – it was released 4 years ago now so a reasonable start point).

This means that I am happy to use css Flex which makes this insanely simple compared to the old days. You just need display:flex;align-items:center in the container div and its content items will centre vertically.

I’ve just used this on a PrimeNG data list component to centre left thumbnails correctly in a list item with no issues.

Quite why we have had to suffer for so many years with arcane tricks (or risk ridicule by making it simple using tables for layout) is beyond me, but there we are.

No Comments »

May 14th, 2017
10:53 am
Web App container layout– how to fill space to right

Posted under Angular & CSS & PrimeNG
Tags , ,

I was trying to allow a left div for a menu to have a percentage width, possibly with a fixed min-width.

I then wanted to add a right div which filled all the remaining space to the right, to form a content pane.

My initial attempts which failed were:-

1/ Float both divs left – this partly works e.g. if I gave 25% width to the left and 75% width to the right, i.e. I had to assign width. If I then gave a min-width to the left, the right div drops underneath when the min-width kicks in.

2/ Per this post here, I took the float out of the right div. Whilst it extended to fill the right hand space, it also filled the left hand space, and placing e.g. a PrimeNG toolbar in the right hand pane resulted in a mess where the height of the toolbar filled the whole height of both divs. This was all due to the interaction of the floated and non floated div – the non floated one just flowed around the left hand floated div, and its content was in fact also hiding underneath the right one. In fact the comments mention that the proposed solution in the post does not work exactly as I found.

Finally an interesting solution which did work is this post here. The right float is not floated but is set to overflow:hidden. This triggers a Block Formatting Context, which interacts with the float to fill the remaining space. The right div becomes a BFC which prevents sibling floats from intruding on them, and also prevents descendant floats from escaping. The post explains the details on this well.

This worked correctly, even when the min-width was used in conjunction with a percentage width for the left div. A plunker showing a simple example of the BFC may be found here.

In the end I abandoned this approach of rolling my own layout. I was using PrimeNG components, and PrimeNG comes with a Grid CSS layout component which does full responsive 12 column based layout. It is nestable, and adaptable automatically for different screen widths via media queries. It is also used internally for the PrimeNG components, so will play nicely with them and will be less prone to side effects. I note from the comments that Bootstrap responsive column layout does not work well with PrimeNG, so I stuck with PrimeNG as it is flexible and easy to use.

Another alternative for grid layout which is big in this area is Foundation, which is also reviewed and compared with Bootstrap here. Bootstrap may be found here. Both Foundation and Bootstrap are frameworks offering components and css/theming as well as grid layout so would likely fight with Primefaces as this post indicates. It looks like you may be able to just get the grid with Foundation by now, not sure with Bootstrap.

No Comments »

July 26th, 2011
10:31 am
Extra unwanted margin around an HTML textarea in Google Chrome

Posted under CSS
Tags , , , , , ,

Chrome places an unwanted 4px bottom margin on a textarea, which is impossible to elminate purely by the margin settings.

In addition, the other browsers sometimes have related issues.

This post on StackOverflow discusses the issue, and the Chrome bug issue may be found here.

Issues like this can be caused in inline and inline-block elements, due to side effects of the line height/vertical alignment of textual elements. They can be hard issues to diagnose as the cause of the extra margin is not readily visible in tools like Firebug or Chrome’s developer tools/debugger. In order to see it, I added an extra div with a border around the element, and the margin was then clearly visible, but of course it was still not reported as a margin on the textarea element, which steadfastly maintained its story that no margin was present!

As per the StackOverflow article, there are 2 ways around this issue:-

  • If the textarea is set to have vertical-align:top then this eliminates the problem. It also has the advantage of maintaining the element as inline-block – in Chrome’s case this is the default, and with other browsers this will often be used in order to allow margins etc. which an inline element will not allow.
  • Another fix for the problem is to set the textarea to display:block, i.e. to make it a block element. This is fine, but it should be noted that as the element is not natively a block type element, IE7 and earlier IE versions will not handle this. IE8 and IE9 will allow an inline element to be redesignated as a block one. Therefore, the first method has better browser compatibility.

No Comments »

July 26th, 2011
10:05 am
Controlling textarea resizing in HTML

Posted under CSS
Tags , , ,

A number of web browsers (notably Firefox, Google Chrome and Apple Safari) have a feature whereby a textarea element in an HTML form can be dynamically resized after rendering, by allowing the user to drag the corner of the element. At the time of writing , IE and Opera do not have this feature.

This is often a desirable feature, but in order to preserve layout it is also desirable to restrict and control it as desired. The following facilities are available to do this:-

  • It can be disabled completely using the css property resize:none. Note that this is a CSS3 property, which limits its scope of use.
  • Another means to do this is by using the min-width, max-width, min-height, and max-height properties, which have the advantage that they are CSS2 properties and therefore more widely supported. They are also more flexible in that they allow precise control of the amount of resizing allowed on the element. Resizing can be disabled completely by setting the minimum and maximum width/height to the actual width/height values.

No Comments »

July 21st, 2011
10:58 am
More useful Posts about inline-block and alignment

Posted under CSS
Tags , , , , ,

Update 18/1/2012

I was having trouble getting cross theme and cross browser consistency in aligning text adjacent to an icon in a series of IconTextButtons of mine, inside a toolbar.

Both the icon and the text were in spans set to display:inline-block and the spans were inside a div. I found the following useful in solving the issue :-

  1. The key issue turned out to be that the line-height was very different across Primefaces themes. The font size was constant at about (effectively) 11.5px, but the effective line-height varied with the them between 12px and 16px. This was the main cause of the issue in getting good alignment.
  2. I just set a fixed line-height of 14px for all the buttons in the toolbar, and this solved the cross theme (and cross browser) issues.
  3. The text was to the right of the icon, and found that tweaking the top margin for the icon set the position of both it and the text vertically, due to the adjacency-relative way in which vertical-align works.
  4. In order to adjust the vertical alignment of the text slightly relative to the icon, I found that setting a small bottom margin on the text achieved this, so one to bear in mind when experimenting.
  5. I had also tried padding changes as well as margin, but the effects (or lack of them) were similar to tweaking the margins.

 

Original Post

This post gives a good description of the effect on margins and padding for inline vs. block elements elements.

This StackOverflow post point out the effect of adjacent inline elements on the vertical alignment of an element – in this case an element was pushed down a few pixels due to the prescence of adjacent inline elements.

I was trying to align text and buttons in a narrow vertical toolbar, and as I have found previously, different browsers render differently.

The best consistency across browsers was obtained as follows :-

  1. Use display:inline-block to allow vertical margins to be obeyed on the elements. They can then be precisely adjusted (but may still behave differently depending on the adjacent elements). inline-block has decent cross browser support. IE6 and IE7 only support it on elements with a native type of ‘inline’ – see this post for cross browser support details.
  2. Using vertical-align:bottom seems to give the best cross browser consistency.
  3. Top and/or bottom margins generally need to be tweaked for each individual case depending on element adjacency. (Depending on the case you may need to set a top or a bottom margin to have the desired effect consistently across browsers.) For example, I had to treat a text only span differently to a text span adjacent to a couple of buttons on the bar.

No Comments »

November 23rd, 2010
11:38 am
Using floats to place a border around a control group/toolbar

Posted under CSS
Tags , , , , , , ,

I originally used display:inline-block, line-height and vertical-align:middle to do this as detailed here, but the results were inconsistent across browsers.

Using floats is a much better solution for a number of reasons – details are as follows:- 

  • The controls are floated left inside a div which is itself floated left. As the div is floating, it auto resizes to fit around the content, and so scales to fit unknown control sizes.
  • The controls are all set to have fixed top and bottom margins (4px in the example), and the leftmost and rightmost also have similar left and right margins respectively.
  • The floated div is set to have the desired border and background etc. – in my case, I use Primefaces/jQuery UI theme style classes to apply theme look and feel.
  • The floated div is then placed inside another outer div, which may be of fixed dimensions. This allows the control group to adjust in size, but to be located inside a fixed area on a page.
  • If the outer div is of fixed size and non floating, the floating inside it is invisible to the rest of the document, so it is not necessary for example to clear the float.
  • If desired, the outer div can be set to overflow:auto to allow scroll bars if the size of the inner floating div exceeds the space allocated for it on the page.
  • If the area surrounding the control group is also floating, the outer div can also be set to float with no size specified, so the concept works well in both floating and fixed size situations.
  • display:inline-block and vertical-align:middle are not used with this method.

 This mechanism has the following characteristics:-

  • The control group bordering works nicely and consistently with the Primefaces/jQuery theme styling, as rather than trying to centre the controls in a fixed border, instead we vary the border size and keep the margin between the controls and the border constant.
  • The approach makes use of the laws of Gestalt Psychology – the eye notices even small imperfections in the alignment of the controls and their relationship to the border because they are close and obviously grouped/related.
  • Conversely the position of the entire bordered control group within its surroundings (the outer div) will typically not be so critical – it will likely be in a larger area of white space between it and adjacent items,  and so its position and size within that space matters less than the control / border relationship.

A caveat to all this is that it is still not perfect – the simple example below does not perform quite as well in terms of cross browser alignment as the Primefaces/jQuery UI version, as the Primefaces themes apply their own styling as well which changes the situation. This could of course be improved by adjusting the margins individually for different controls in the group to get the best overall cross browser alignment. One very important goal I am trying to acheive is to avoid browser specific CSS. The Primefaces/jQuery UI CSS does in general have browser specific tweaks which will help it in certain situations.

Overall though this approach performs significantly better than the previous method using vertical-align:middle etc. and has the advantage of being fully floating/dynamically sizing if required. An example of this approach follows :-

<!DOCTYPE html>
<html>
<head>
 <style type=”text/css”>
  .ss-outerdiv {
   height: 40px;
   width: 200px;
   background-color: orange;
  } 
  .ss-controlgroup {
   float: left;
   background-color: green;
   border: 1px solid black;
  }
  .ss-select, .ss-leftbutton, .ss-rightbutton {
   margin-top: 4px;
   margin-bottom: 4px;
   float: left;
  }
  .ss-select {
   width: 120px;
     font-family: Arial,Verdana,sans-serif;
     font-size: 11px;    
   margin-left: 4px;
   margin-right: 4px;
  }
  .ss-leftbutton, .ss-rightbutton {
   height: 20px;
   width: 30px;
  }
  .ss-leftbutton  {margin-right: 2px;}
  .ss-rightbutton {margin-right: 4px;}
 </style>
</head>
<body>
<div class=”ss-outerdiv”>
 <div class=”ss-controlgroup”>
  <select class=”ss-select”>
  <option value=”Test”>Test Value</option>
  </select>
  <button class=”ss-leftbutton ss-button”></button>
  <button class=”ss-rightbutton ss-button”></button>
 </div>
</div>
</body>
</html>

No Comments »

November 11th, 2010
12:59 pm
Scrollable containers in Primefaces

Posted under CSS
Tags , , ,

Some Primefaces containers appear to support scrolling, but this is not universally supported. Layout panels support it, but ordinary panels appear not to.

Fortunately, with IE7 and above, scrolling on a <div> (JSF panelGroup with layout=”block”) works reliably and consistently across modern browsers, so scrolling can just be added within e.g. within a CSS class rule as follows:-

.ss-scroll {
   overflow:auto;
}

or:-

.ss-scroll {
   overflow: scroll;
}

Using overflow:auto will only add the scrollbars if they are needed, i.e. if content is clipped. Using overflow: scroll will add them all the time so you will get redundant scrollbars when the content does not clip.

Note that for Primefaces, to make a scrolling panel for example, the attribute needs to be added to a containing div inside the panel, and not the panel itself, otherwise the panel header will scroll out of view when the contents scroll which is undesirable.

The w3schools documentation on overflow will be found here.

No Comments »