How to align items in a <h:panelGrid> to the right - css

How would I align everything in my below to the far right?
<div id="container">
<h:form id="authenticate">
<h:panelGrid columns="5" cellpadding="6">
<h:inputText id="email" value="" />
<p:watermark for="email" value="Email"/>
<h:inputSecret id="password" value="" />
<p:watermark for="password" value="Password"/>
<p:commandButton id="login" value="Login" align="right"/>
</h:panelGrid>
</h:form>
</div>

The <h:panelGrid> renders a HTML table. You basically want to apply text-align: right; on every <td> element it renders. With the current code, easiest would be to apply the following:
#authenticate table td {
text-align: right;
}
You can of course also be more specific, e.g. giving the <h:panelGrid> its own styleClass and defining a rule in CSS (which would be applied directly on the rendered HTML <table> element).
<h:panelGrid styleClass="className">
with
.className td {
text-align: right;
}
You can also give each <td> element its own class by columnClasses attribute which accepts a commaseparated string of CSS classnames which are to be applied repeatedly on the <td> elements. If you want to apply the same class on every <td> element, just specify it once:
<h:panelGrid columnClasses="className">
with
.className {
text-align: right;
}
As an extra hint: rightclick the webpage in webbrowser and choose View Source, then you'll understand better what JSF is all exactly generating.

actually in same form i used <p:panel> and got good result. looks like ;
<p:panel styleClass="ui-panel-titlebar ui-widget-header ui-helper-clearfix ui-corner-all">
<p:commandButton value="Add New Tab"
actionListener="#{xxx.createNewTab}" process="#this"
update="tabView" style="float:right !important;margin:0px 0px 3px 0px;" />
</p:panel>

A little late, but might help someone, as it was what I needed...
If the alignment is not limited to this specific table, but rather the default format for all table cells, then just add this to your CSS file:
td {
text-align: right;
}
Then, all <td> elements, including those generated by JSF, will be formatted that way.

Related

Applying StyleClass to Input text [duplicate]

This question already has answers here:
How do I override default PrimeFaces CSS with custom styles?
(5 answers)
Closed 7 years ago.
I have been trying to apply style class to my input text but I am unable to do it .
<h:form id="SearchPageForm">
<br />
<p:outputLabel>Search: </p:outputLabel>
<p:inputText id="search" styleClass="text-input" size="123"
value="${SearchController.employeeBO.employeeID}" />
<h:commandButton value="submit" image="images/search.png"
style="vertical-align: top;" action="#{SearchController.searchOnId}" />
<br />
<br />
This is my HTML and my CSS says
.text-input{
background-color:#fbfbfb;
border:solid 50px #000000;
margin-bottom:8px;
width:750px;
padding:8px 5px;
color:#797979;
}
I did the inspect on the form and I see it is still calling the default CSS of primefaces.
<input id="SearchPageForm:search" name="SearchPageForm:search" type="text" size="123" class="ui-inputfield ui-inputtext ui-widget ui-state-default ui-corner-all text-input" role="textbox" aria-disabled="false" aria-readonly="false" aria-multiline="false">
I want to increase the size of Search Form to 750px .
I am new to CSS and HTML so might have missed something .
Regards
To debug the css properties you could use the function "inspect element" that all browsers have, and so you can see if the css properties are being aplied.

Apply styleClass to parent panelGrid element and not to children

I'm trying to apply a styleClass to a h:panelGrid without applying it to its children:
<h:panelGrid id="mainPanelGrid" columns="2" width="100%" styleClass="topAligned" >
<p:fieldset id="fs1" legend="fs1" style="width: max-content">
<h:panelGrid columns="3">
<p:outputLabel for="id1" value="#{messages.label_application}" />
<p:selectOneMenu id="id1" required="true" value="som">
<f:selectItem itemLabel="#{messages.label_select}" noSelectionOption="true" />
<f:selectItems value="#{bean.availableItems}" />
</p:selectOneMenu>
<p:message for="id1" />
</h:panelGrid>
</p:fieldset>
<p:fieldset id="fs2" legend="fs2" style="width: max-content">
<h:panelGrid columns="3">
<!--more fields-->
</h:panelGrid>
</p:fieldset>
</h:panelGrid>
My topAligned css:
.topAligned td{
vertical-align: top !important;
}
The problem is that I need to top align the two fieldset and that works well with the styleClass I apply, but it also applies this styleClass to all the children. Therefore, all the fields (outputLabel, selectOneMenu, etc...) of the two fieldset get top aligned too...
I tried all the different ways to specify the top alignment from this question but without success... I also tried to look at the html source but it gets a bit confusing with all the jsf and primefaces stuff...
If you know a trick that will work...
With
.topAligned td{
vertical-align: top !important;
}
and the JSF-generated HTML output
<table class="topAligned">
...
</table>
you're basically applying the style on every single <td> element of the <table>, also those of the nested <table>s.
If you want to apply the style on only the immediate <td> elements of the parent <table>, then you should be using columnClasses attribute instead:
<h:panelGrid ... columnClasses="topAligned,topAligned">
with
.topAligned {
vertical-align: top;
}
This will end up in the generated HTML output as follows:
<table>
<tbody>
<tr>
<td class="topAligned">...</td>
<td class="topAligned">...</td>
</tr>
</tbody>
</table>
and not be applied on the <td>s of the nested <table>s.
Note that I also removed the nonsensicial !important workaround. It's supposed to be used only when you want to override a hardcoded style by an external CSS style.
Also note that this problem is not specifically related to JSF. JSF is in the context of this question merely a HTML code generator. You'd have had exactly the same problem when dealing with "plain vanilla" HTML/CSS. The problem is more in the lack of familiarity with basic HTML and CSS. On http://htmldog.com you can find decent HTML/CSS tutorials.

Force linebreak OutputLabel

I have an outputLabel which contains a lot of text (about 5000 characters of text), the outputLabel has to add a new line after the line is about 200px, is this possible?
<p:outputLabel value="#{object.body}" />
<p:outputLabel value="#{object.body}" style="width: 200px" />
This code doesn't work:
public String getBodyWithLineBreaks(){
return body.replaceAll("(.{100})", "$1<br/>");
}
It is also not a solution because this method does not look if a word is finished, it just starts a new line at the 100th character.
Some more code:
<p:dataTable id="dataTable" var="object" value="#{notificationOverview.objects}">
<!--Some more columns...-->
<p:rowExpansion>
<h:panelGrid id="display" columns="2" cellpadding="4" style="width:300px;"
styleClass=" ui-widget-content grid">
<f:facet name="header">Notification Information</f:facet>
<h:outputText value="Sender:"/>
<h:outputText value="#{object.sender.username}"/>
<h:outputText value="Time send:"/>
<h:outputText value="#{object.dateSend}">
<f:convertDateTime pattern="yyyy-MM-dd HH:mm:ss"/>
</h:outputText>
<h:outputText value="Title:"/>
<h:outputText value="#{object.title}"/>
</h:panelGrid>
<br/><br/>
<div style='width: 200px;'>
<h:outputText value="#{object.body}" />
</div>
</p:rowExpansion>
</p:dataTable>
The <p:outputLabel> generates a HTML <label> element which is by default an inline element. You can't set the dimensions of an inline element. You can only set it on a block element.
One way would be adding display: block to the style.
<p:outputLabel value="#{object.body}" style="display: block; width: 200px;" />
Additionally, given that this is inside a <p:dataTable> cell, which has by default its CSS white-space property set to nowrap, you need to set it back to normal. This can be set on the same component, but this is preferably to be set on the parent <p:column> itself:
<p:column style="white-space: normal;">
Note: as part of a good practice, you should prefer styleClass over style.
Unrelated to the concrete problem, the HTML <label> element is designed to label an input element which is identified by for attribute. I.e. when you click on it, the associated input element retrieves focus (and a checkbox/radiobutton get selected). When validation is performed, the label is used to identify the input element. However, the fact that you're trying to display 5000 characters inside a label element, which is completely user unfriendly when used as a real label, suggests that you're actually abusing the label for the wrong purpose of displaying "plain text". You should be using <h:outputText> instead. This generates a HTML <span> element which is by default also an inline element. So the above answer applies on that as well:
<h:outputText value="#{object.body}" style="display: block; width: 200px;" />

JSF panelgrid alignment to top

I see there are some answers posted for this. tried almost all of them with several permutation-combination.. but nothing seems to be working.
components inside panelgris are always middle aligned, instead of top.
tried whatever they said in the below post.
How to control alignment of DataTable inside of a PanelGrid?
Please let me know if there is a remedy.
The <h:panelGrid> renders a HTML <table> element. The vertical alignment of a table cell <td> defaults indeed to middle. You want to make it to be top instead. This is easy with CSS.
<h:panelGrid styleClass="foo">
with
.foo td {
vertical-align: top;
}
If you have a table inside the panelgrid for which you'd like to keep the default table cell vertical alignment of middle, then you need to alter the CSS as follows:
.foo>tbody>tr>td {
vertical-align: top;
}
so that only the panelgrid's own table cells are top aligned.
To learn all about CSS, check http://www.csstutorial.net.
Use the panelGrid's columnClasses attribute to identify a CSS class that includes the vertical-align: top; style:
<h:panelGrid columns="2" columnClasses="topAligned">
...
</h:panelGrid>
and the CSS file:
.topAligned {
vertical-align: top;
}
The contents of the first column in the panelGrid will then be top-aligned within their cells.
Use the styleClass for the panelGrid as in the following example code:
<h:panelGrid columns="2" styleClass="top-aligned-columns" cellpadding="5" style="display:block" cellspacing="5">
<p:outputLabel value="#{resources['IDNumber']}" />
<p:inputText id="txtIDNumber" value="#{applicantBean.personal.idNumber}" />
</h:panelGrid>
Then in the css configure as follows:
.top-aligned-columns td{
vertical-align: top;
}
With this method you will be able to not only top-align the rows but you can also apply the same styleClass to other panelGrids within the encompassing panelGrid.
For example:
<h:panelGrid columns="3" styleClass="top-aligned-columns" cellpadding="5" style="display:block" cellspacing="5">
<p:panel id="pnlApplicant" header="#{resources['ApplicantHeader']}" styleClass="no-border">
<h:panelGrid columns="2" cellpadding="5" style="display:block" cellspacing="5" styleClass="top-aligned-columns">
<p:outputLabel value="#{resources['IDNumber']}" />
<p:inputText id="txtIDNumber" value="#{applicantBean.personal.idNumber}" >
<p:ajax event="change" process="#this" update="tvQuickScore"/>
</p:inputText>
<p:outputLabel value="#{resources['Name']}" />
<p:inputText id="txtFirstname" value="#{applicantBean.personal.firstName}" />
<p:outputLabel value="#{resources['Surname']}" />
<p:inputText id="txtSurname" value="#{applicantBean.personal.lastName}" />
</h:panelGrid>
</p:panel>
</h:panelGrid>
</p:panel>

Best strategy to style the same HTML when it appears on multiple pages

I have a simple HTML table with 2 columns containing text fields and headers for 'Name', 'Comments' and 'Email'.
I'm looking for the best strategy on styling this HTML fragment if it were to appear on multiple pages - requiring different dimensions on each page. I've been reading a lot about CSS recently but havent stumbled across enough information yet that really makes me comfortable to know the best way to design such .css.
For instance I might show the comments form at 50% width on the 'comments' page, but only at 20% in a sidebar in some additional places on the site.
I am mainly concerned about styling the widths of the boxes - but of course the same approach applies for the text. For instance the name field should not be as wide as the email field. I'm thinking fixed widths are better than percentages.
There are obviously many ways to style it. Assume I have 1 master css file already.
1) Put percentage widths on the input tags and then the outer div would be 100% width for whatever panel it is contained in. This requires no page specific css but I don't like the idea of percentages inside the td tags, plus I cant change the height easily of the textarea.
2) create styles for #Name, #Comments and #Email in each individual page as additional styles in <head><style> *
3) style based on #Name, #Comments and #Email in a page specific css file. Are page specific files good or bad? I'm not even sure I like styling based on the ids here because they're dynamically generated and if for some reason they needed to change I'd have to update the css everywhere.
4) style based on #Name, #Comments and #Email but qualify them with a descendent selector specific to each page. So i'd have .faqPage #Name for when this appears on the FAQ page. Obviously these go in my master css file.
5) create class names for 'emailField,nameFieldandcommentsField` [options 2,3,4 are repeated for this option]
6) create class names for 'shortField,fullWidthFieldandtextInputField` [options 2,3,4 are repeated for this option]
7) you get the idea :)
8) something else
I'm just a little overwhelmed with all the options. How do I go about deciding which is the best way? A specific goal is to be able to style the same HTML on multiple pages (obviously thats what css is all about though - but it does affect which options I can use).
<div id="pnlSubmitComments">
<table class="fieldTable">
<tr>
<td align="right">
<label for="Comments">Name:</label>
</td>
<td>
<input id="Name" name="Name" type="text" value="" />
</td>
</tr>
<tr>
<td align="right">
<label for="Comments">Email:</label>
</td>
<td>
<input id="Email" name="Email" type="text" value="" />
</td>
</tr>
<tr>
<td align="right" valign="top">
<label for="Comments">Questions:</label>
</td>
<td>
<textarea id="Comments" name="Comments">
</textarea>
</td>
</tr>
<tr>
<td>
</td>
<td>
<input id="btnSubmitComments" name="btnSubmitComments" type="submit" value="Submit Questions" />
</td>
</tr>
</table>
</div>
PS. The actual field names more specific such as CommentsName - its just easier to put Name here for readability.
Side comment: Maybe you shouldn't use tables to layout this form but fieldsets, it would leave you with more flexibility. For example if you decide to have the labels and input fields on top of each other in a more narrow column...
your example without tables (looks also much prettier):
<style type="text/css">
<!--
form { /* set width in form, not fieldset (still takes up more room w/ fieldset width */
font: 100% verdana, arial, sans-serif;
margin: 0;
padding: 0;
min-width: 500px;
max-width: 600px;
width: 560px;
}
form fieldset {
/* clear: both; note that this clear causes inputs to break to left in ie5.x mac, commented out */
border-color: #000;
border-width: 1px;
border-style: solid;
padding: 10px; /* padding in fieldset support spotty in IE */
margin: 0;
}
form fieldset legend {
font-size: 1.1em; /* bump up legend font size, not too large or it'll overwrite border on left */
/* be careful with padding, it'll shift the nice offset on top of border */
}
form label {
display: block; /* block float the labels to left column, set a width */
float: left;
width: 150px;
padding: 0;
margin: 5px 0 0; /* set top margin same as form input - textarea etc. elements */
text-align: right;
}
form input, form textarea {
/* display: inline; inline display must not be set or will hide submit buttons in IE 5x mac */
width: auto; /* set width of form elements to auto-size, otherwise watch for wrap on resize */
margin: 5px 0 0 10px; /* set margin on left of form elements rather than right of
label aligns textarea better in IE */
}
textarea {
overflow: auto;
}
/* uses class instead of div, more efficient */
form br {
clear: left; /* setting clear on inputs didn't work consistently, so brs added for degrade */
}
-->
</style>
<div id="pnlSubmitComments">
<form>
<fieldset>
<label for="Comments">
Name:
</label>
<input id="Name" name="Name" type="text" value="" /><br />
<label for="Comments">
Email:
</label>
<input id="Email" name="Email" type="text" value="" /><br />
<label for="Comments">
Questions:
</label>
<textarea id="Comments" name="Comments">
</textarea><br />
<label for="spacing"></label>
<input id="btnSubmitComments" name="btnSubmitComments" type="submit" value="Submit Questions" />
</fieldset>
</form>
</div>
Now to your main question. I would do it as follows:
I would use the id's of the different layout columns I want to use the form in. So if I use it in my main column () I would write CSS accordingly like so:
#main .pnlSubmitComments form fieldset {
/*your CSS*/
}
and for the side column respectively
#side .pnlSubmitComments form fieldset {
/*your CSS*/
}
You can have control over each element by assigning classes like so:
<input type="text" class="email" name="email" id="email" />
and then you do exactly as described above:
#main .email {
/*your css for the .email textbox/*
}
You can easily do it with one css file, if you can add a style class on a container element.
For example, page 1 would have the following html:
<body class="page1">
<!-- repeated html here -->
<input />
</body>
And on page 2 you'd have:
<body class="page2">
<!-- repeated html here -->
<input />
</body>
In your single css file you can target the input tags based on the class of the body element:
body.page1 input { width: 25%; }
body.page2 input { width: 50%; }
So, you keep the html the same, just change the class (or id) of a container element, and use that to write different css rules.
Update: After rereading your list, i see this is more or less on your list as number 4. I think this is a good option if you can use it. I also use it to target different browsers, by adding a class indicating the browser on a body tag.
1) Use common css and set some of the values like width in code behind.
2) Create multiple css files for different needs and link right css to page using code behind.
Sorry it took so long to get back to you!
CSS-GRID with grid-template-areas is a fantastic way to do this!
You can name regions and then switch the css with responsive media queries and change the layout without ever having to rearrange the HTML.
https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-areas

Resources