Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vertical alignment in format expression #832

Open
stanislawpuda-tomtom opened this issue Sep 25, 2024 · 18 comments
Open

Vertical alignment in format expression #832

stanislawpuda-tomtom opened this issue Sep 25, 2024 · 18 comments

Comments

@stanislawpuda-tomtom
Copy link

stanislawpuda-tomtom commented Sep 25, 2024

Design Proposal: Add vertical alignment to format expression

Motivation

Format expression can facilitate multiple text and image elements of different sizes. At the moment all of them are aligned to the font baseline. It is not possible to change the vertical alignment. Having a possibility to change the alignment, eg. center, would allow us to create rich labels.

If following design would be accepted I would like to make contributions to this repo and MapLibre GL JS with the implementation.

Proposed Change

We would like to introduce vertical-align property to style override in format expression. vertical-align property can take three options:

  • bottom (default)
  • center
  • top

Examples

Center

"text-field": [
  "format",
  ["image", "image"], 
  { "vertical-align": "center" },
  " ",
  {},
  "BIG yg",
  { "font-scale": 1.2, "vertical-align": "center" },
  " ",
  {},
  "SMALL",
  { "font-scale": 0.8, "vertical-align": "center" }
],

big_image_center
small_image_center

Top

"text-field": [
  "format",
  ["image", "image"], 
  { "vertical-align": "top" },
  " ",
  {},
  "BIG yg",
  { "font-scale": 1.2, "vertical-align": "top" },
  " ",
  {},
  "SMALL",
  { "font-scale": 0.8, "vertical-align": "top" }
],

big_image_top
small_image_top

Bottom (default, current behaviour)

"text-field": [
  "format",
  ["image", "image"], 
  {},
  " ",
  {},
  "BIG yg",
  { "font-scale": 1.2 },
  " ",
  {},
  "SMALL",
  { "font-scale": 0.8 }
],

big_image_baseline
small_image_baseline

Mixed

"text-field": [
  "format",
  ["image", "image"], 
  {},
  " ",
  {},
  "BIG yg",
  { "font-scale": 1.2 },
  " ",
  {},
  "SMALL",
  { "font-scale": 0.8, "vertical-align": "center" }
],

big_image_mixed

API Modifications

Add new property to style override object of format expression:

vertical-align:

  • type: enum
  • default: bottom
  • possible values: bottom, center, top
  • effect: change vertical alignment of format expression element

Behaviour

  • bottom default: text baseline and image bottom are in line (current behaviour)
  • center: image center and text center (line between baseline and top) are in line with center of the highest element in the row
  • top: image top and text top (line determined by the highest character in the font) are in line

It is possible to set vertical-align for each element in format expression separately.

Migration Plan and Compatibility

There is no breaking change. Rendering of existing styles is unchanged. Only if style has new property vertical-align with non-default value, there is a difference in label rendering.

@HarelM
Copy link
Collaborator

HarelM commented Sep 25, 2024

Thanks for taking the time to open the proposal!
What are the current alternatives available?
My concern is the this is a bit two simplistic. What about if I want to move a single word two pixels upwards? What about padding between words?
This might get very complex...

@stanislawpuda-tomtom
Copy link
Author

I understand your concern. I believe what you've mention can be achieved by combining together additional property.

If we want to move single word a few pixels, we could add vertical-offset. Examples:

  • element aligned to the top and shifted two pixels down: { "vertical-align": "top", "vertical-offset": "-2px" }
  • element aligned to the center and shifted two pixels up: { "vertical-align": "center", "vertical-offset": "2px" }
    "offset" property maybe could take also relative values, but it should be well thought out to make it intuitive.

For the padding between words the easiest solution is to use spaces. I'm not sure if this requires another solution.

For the alternatives, we did think of numeric based approach, where value moves element up and down. There are two possibilities:

  • where numeric value stands for relation between baseline of the row and element vertical position. Eg. 0 - baseline of the element = baseline of the row, 0.5 - element shifted 50% of its height up, -0.5 or center, middle of the element in line with row baseline. However, this approach is not working when elements (especially images) can have various height.
  • similar to vertical-align but with numbers: 0 for baseline, 0.5 for middle and 1 for top - but enum variant is in my opinion easier to understand

@zbigniewmatysek-tomtom
Copy link

I propose to rename this property, because it suggests it works like https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align, but in reality is similar to the https://developer.mozilla.org/en-US/docs/Web/CSS/align-self.

I belive showing the analogy to CSS properties can be helpful. It is easier to explain and adopt trough using existing terminology.

Regarding the @HarelM concern on the extendibility of this proposal. I think it's pretty extensible. One solution is having relative offset property that @stanislawpuda-tomtom explained or a different set of properties altogether that may or may not be combained with the vertical-align.

@HarelM
Copy link
Collaborator

HarelM commented Sep 29, 2024

I would advise to bring this up in the monthly meeting to discuss this.

@stanislawpuda-tomtom
Copy link
Author

Will do!

Regarding the name, I went through few possible options:

  • row-align,
  • align-vertical,
  • vertical-placement,
  • y-align?

But to be honest, vertical-align still sounds for me like the best option. I'm not sure if the connotations with CSS property is so significant.

@HarelM
Copy link
Collaborator

HarelM commented Nov 27, 2024

Google docs has these settings:
Image

Microsoft word has "Align Top/Middle/Bottom" and "Align Left/Center/Right".

So I would change the enum to be Top/Center/Bottom or Top/Middle/Bottom.
I tend to agree that when I read the CSS of self-align I have no understanding of what self means in that aspect...

So, if there are no more comments I guess this can be pushed forward.

@stanislawpuda-tomtom
Copy link
Author

stanislawpuda-tomtom commented Nov 28, 2024

@HarelM

Done, I've changed the PR. #900

@HarelM
Copy link
Collaborator

HarelM commented Nov 28, 2024

@zbigniewmatysek-tomtom any feedback on the above?

@zbigniewmatysek-tomtom
Copy link

@HarelM
Baseline aligns bottom of line elements to the baseline of the text, this is not the same as the bottom alignment which aligns elements to the bottom of the tallest element.

If we decide to extend spec to support bottom alignment, it will be cumbersome to name it.

I like the "Middle", since it reflects that alignment is in a single axis.

How about Top/Middle/Baseline?

And in the future (if someone finds it useful): Top/Middle/Baseline/Bottom

@HarelM
Copy link
Collaborator

HarelM commented Nov 28, 2024

I'm not sure baseline is intuitive, it's not intuitive to me at least...

@zbigniewmatysek-tomtom
Copy link

LGTM.

I also don't see an use case for the bottom, but I wanted to raise this just in case. We can go with your proposal.

@louwers
Copy link
Collaborator

louwers commented Nov 28, 2024

What is the difference between bottom and baseline?

@louwers
Copy link
Collaborator

louwers commented Nov 28, 2024

I tend to agree that when I read the CSS of self-align I have no understanding of what self means in that aspect...

It's the piece of text or image that the format override applies to.

By the way, there is a CSS vertical-align, why not use the same terms as that? https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align

Image

Image

@zbigniewmatysek-tomtom
Copy link

@louwers

#832 (comment)

The behavior of css vertical-align is very different from the behavior we want to achieve here.

@louwers
Copy link
Collaborator

louwers commented Nov 28, 2024

@zbigniewmatysek-tomtom Care to explain what the difference is?

@louwers
Copy link
Collaborator

louwers commented Nov 28, 2024

I think I understand what you mean. vertical-align: middle does the following:

Aligns the middle of the element with the baseline plus half the x-height of the parent.

Image

Here pink is middle, orange is top and green is baseline. The SMALL in the last row is not in the middle of the entire line.

In fact, vertical-align does not have a line-relative value for the center/middle:

Image

It does for table cells though:

Image

https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align

@louwers
Copy link
Collaborator

louwers commented Nov 28, 2024

top: image top and text top (line determined by the highest character in the font) are in line

I assume the tallest image of the format expression also participates in determining the top line?

@stanislawpuda-tomtom
Copy link
Author

@louwers

I assume the tallest image of the format expression also participates in determining the top line?

This is correct - the highest section of the line, can be either image or text

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants