Overlaying a Label on an image within a Container (CSSGridItem or Container)

On a form, I can add an image, then add a label, and then move the label over the image. I can even change the zOrder by moving the controls up and down in the project explorer, if I added forward items first.

But when I do the same by adding an image and label control to a CSSGridItem I can’t find a way to change their position relation to the 0,0 coordinate of the griditem. EG, the bounds seem to be ignored. I’ve tried many of the setting for the griditem and the children, but nothing has allowed the overlaying of the text on the image in the griditem. What’s the secret?

What type of container are you putting the image and overlay text in?

A CSSGridItem control (common control in AppStudio).

I get that… But inside the grid cell what are you wrapping YOUR content/card in? A div? A span?

The inspector shows the CSSGridItem as a div. the image and label are children, label is defined second, right now:

<div id="CSSGridItem1" class="" style="font-family:inherit;border-width:1px; border-color:#E0E0E0; "><div id="Image2" data-nsb-type="image" style="overflow:hidden;" class=""><img src="images/AdobeStock_241483334.jpeg" height="100%" width="100%" id="Image2_img" usemap="Image2_map"></div><div id="Label2" class="" data-nsb-type="Label" style="cursor:default;text-align:center; text-shadow:none; font-size:16px;font-family:inherit;font-weight:bold;color:rgb(255,255,255); ">Label</div></div>

So lets look at this code:

<div id="CSSGridItem1" class="" style="font-family:inherit;border-width:1px; border-color:#E0E0E0; ">
  <div id="Image2" data-nsb-type="image" style="overflow:hidden;" class="">
    <img src="images/AdobeStock_241483334.jpeg" height="100%" width="100%" id="Image2_img" usemap="Image2_map">
  </div>
  <div id="Label2" class="" data-nsb-type="Label" style="cursor:default;text-align:center; text-shadow:none; font-size:16px;font-family:inherit;font-weight:bold;color:rgb(255,255,255); ">Label</div>
</div>

You have an outer div which is the grid cell (item1) or parent of the following divs. Then inside that parent div you have another div (image2) which is the image and it takes up 100% of the parent div (item1). Below that the image div you have yet another div (label2) which is also a child of item1).

The div tag is short for “content division” and, by default, div’s are block items (think of a paragraph as a block) and they don’t naturally sit next to each other nor on top of each other. To “fix” this there are several css properties that allow you to change some of the behavior.

I’ll direct you to this link at w3schools. so read up on that and when you get down to the example that shows display: block; click the “try it” button and run that code and then try changing that “display: block” to “display: inline” and run it again and see what happens.

BTW, once you see how “display: inline” works, try playing with the margins on that div like this:

div { 
  display: inline;
  margin-left: -25%;
}

Yes, I see how inline works. and the margin negative percentage. A bit sloppy (picking the correct negative percentage) and hard to make happen. And if the text is variable and needs to be centered over the image, … It seems like there must be a better way.

I’m not convinced that you are correct that this is a div issue, as this does work when these two controls are children of a form. Here’s how it’s defined, and it overlays just fine.

   <div id="Image4" data-nsb-type="image" style="overflow:hidden;" class="">
         <img src="images/Small_268057087.jpg" height="100%" width="100%" id="Image4_img" usemap="Image4_map">
         </div>
   <div id="Label4" class="" data-nsb-type="Label" style="cursor:default; text-shadow:none; font-size:16px;font-family:inherit;font-weight:bold;color:rgb(255,0,0); ">Label</div>

This is of course inside the div for the FORM (appstudio form) at the level just below the FORM div.

There are other options besides the -% but I just wanted you to see the effect between block vs inline.

If you look at the elements in chrome and scan down the .css properties you’ll see what some of your options are.

Actually, there is an easy way to do it in the AppStudio IDE.

Set the position attribute of the CSSGridItem to absolute. For the children: the image, the bottom item in the zOrder, must have the size set. Then the left and right of all of the child items becomes absolute within the griditem. These properties must be specified for all children. Making the two child items the same size and using the same left and top values (probably 0 for left and top) will ensure they are over each other on all edges. And this maintains a clean rendering in the IDE.

Nice find! What code and css is behind it?

However, that does not work. All of the GridItems end up at the same absolute position. What works is adding a Container under the GridItems that holds the image and label. The Container is set to absolute position, while the GridItems stays with position relative. The complete settings appear to be:

  • CSSGrid - auto on height/width, integer position on left and top, display blank, position relative
  • each CSSGridItem - actual height and width, auto left and top, display in-line grid, position static
  • each Container under each CSSGridItem - actual height and width, auto left and top, display flex, position absolute
  • each Image under each Container - actual height and width, auto left and top, display blank
  • each Label under each Container - actual height and width of image, auto left and top, align center, alignVertical center, display blank

These are the settings as presented in the IDE. For those who want to see how it came out, here’s the form (I removed the duplicate CSSGridItems for brevity, (which doesn’t really exist), as they are all identical to the first one):

<a name="/Home" data-role="none"></a><div id="Home" class="nsb-form " style="display: block; background-color: rgb(0, 0, 0); position: absolute; height: 100vh; top: 0px; left: 0px; width: 100%; transition-timing-function: cubic-bezier(0.1, 0.57, 0.1, 1); transition-duration: 0ms; transform: translate(0px, 0px) scale(1) translateZ(0px);"><div id="CSSGrid1" class="" style="align-content:start; grid-column-gap:4px; grid-row-gap:4px; justify-content:start; font-family:inherit;border-width:1px; border-color:#E0E0E0; "><div id="CSSGridItem1" class="" style="margin:3px; font-family:inherit;border-width:1px; border-color:#E0E0E0; "><div id="Container1" class="" style="font-family:inherit;border-width:1px; border-color:#E0E0E0; " data-i18n="Content"><div id="Image2" data-nsb-type="image" style="overflow:hidden;" class=""><img src="images/AdobeStock_241483334.jpeg" height="100%" width="100%" id="Image2_img" usemap="Image2_map"></div><div id="Label2" class="" data-nsb-type="Label" style="cursor: default; text-align: center; text-shadow: none; font-size: 16px; font-family: inherit; font-weight: bold; color: rgb(255, 0, 0); line-height: 100px;">Login</div>Content</div></div>

After more consideration, I think it would be best if the Image and Label used left and top of 0. If I have other items I want to place in the grid item, it would probably be by absolute position, especially since I have overlapping items.

Also, I think it is good to set the gridTamplateColumns and gridTemplateRows properties of the CSSGrid control to empty since we are not using a fixed layout. Someone may be confused by the 3 columns/rows default.

Otherwise the settings seem to work well.

A final gotcha came up on this one. It seems that when I create a label (common controls) and set it to align and vertical align to center, and set the height to a fixed integer, and then addchild the label to a Container control that is within a CSSGridItem control, the line-height attribute is lost by the IDE. I simply added it back into the style of the control in the IDE. But it seems odd it goes away. This is needed for the vertical centering to work.

CSS is always an adventure. One useful tool is in the Chrome’s right click - Inspect. The right panel shows all the CSS rules which apply to the element and where they come from. The ones at the top have precedence: the top applicable rule for a style replaces any others.

The Computed tab is also useful: it should the actual values for the styles.

George, does the IDE drop the line-height attribute by design, or is this a bug?

Have a look the the Inspect panel - it might give a clue what happened to this. There are too many moving parts here for me to guess what the CSS will do.

I have been, that’s how I noticed the line-height was missing. It is missing in the IDE when you addchild a label into a container. Not sure why the addchild drops it, but it does. As I said, I just added the style back in the style property of the label (in the IDE) and it works fine. Just took a long time to find it in Chrome inspector.