Angular Material Rotate Ink Bar to Vertical Orientation

After wanting to change the orientation of Angular Material's Tab Component to vertical, I visited this page (Tabs) and experimented with the CSS. By making the necessary adjustments, I successfully displayed the tabs vertically using the following CSS:

.mat-tab-group {
    display: flex;
    flex-direction: row!important;
}
.mat-tab-labels {
    display: flex;
    flex-direction: column!important;
}

However, the mat-ink-bar remained at the bottom as expected: https://i.stack.imgur.com/fM7Y3.png

I am now wondering how I can rotate the bar to be vertical and position it at the right side of the tab labels while keeping its transition intact.

My current solution involves rotating the bar 90 degrees clockwise and aligning it properly on the right side. Additionally, adjusting the width of the bar to match the height of the tabs could create a more seamless display.

Answer №1

Since no one has provided any code samples, I'll share mine as I was able to figure it out. Credit to the previous answer for the inspiration.

This is how I approached it:

Add the following SCSS code either globally or in the necessary location (If you need basic CSS conversion, that's up to you):

mat-tab-group[vertical] {
  flex-direction: row;

  ::ng-deep mat-tab-header {
    flex-direction: column;
    border-bottom: 0px solid transparent;
    border-right: 1px solid rgba(0, 0, 0, 0.12);

    .mat-tab-label-container {
      flex-direction: column;

      .mat-tab-labels {
        flex-direction: column;
      }

      mat-ink-bar {
        left: initial !important;
        bottom: initial;
        right: 0;
        width: 2px !important;
        height: initial;
      }
    }
  }

  ::ng-deep .mat-tab-body-wrapper {
    flex-direction: column;
    width: 100%;
  }
}

:host-context(.dark) mat-tab-group[vertical] ::ng-deep mat-tab-header {
  border-right: 1px solid rgba(255, 255, 255, 0.12);
}

Next, make these modifications to your component TypeScript file. You can place this in your main app component TS if vertical tabs will be used frequently; otherwise, add it to each relevant component:

Firstly, implement the DoCheck interface and include the following function:

ngDoCheck() {
  document.querySelectorAll("mat-tab-group[vertical]").forEach((verticalTabGroup: HTMLElement) => {
    let inkBar: HTMLElement = verticalTabGroup.querySelector("mat-ink-bar");
    if (!inkBar) {
      return;
    }
    let active: HTMLElement = verticalTabGroup.querySelector(".mat-tab-label-active");
    if (!active) {
      return;
    }
    inkBar.style.top = `${active.offsetTop}px`;
    inkBar.style.height = `${active.offsetHeight}px`;
  });
}

There might be a more efficient way to achieve this in Angular, but coming from a traditional vanilla background, I'm still learning,

One issue remaining is that the tab body may still scroll horizontally when switching tabs. This appears to require altering CSS transform styles through JavaScript, making it difficult to adjust without modifying the original mat-tab-group source code.

Please note that my testing was limited to a basic tab group. I cannot guarantee that pagination arrows will function correctly with this setup. That task is left for the developer who requires it.

For those interested, a potential challenge could involve rotating the entire tab group using CSS transforms, then counter-rotating the tab labels and bodies to recreate the vertical orientation. In theory, this approach should maintain ink bar and body transitions. However, it may be unnecessary complexity.

Answer №2

In my opinion,

<mat-ink-bar class="mat-ink-bar" style="visibility: visible; left: 160px; width: 160px;"></mat-ink-bar>

the key element that requires modification is the one mentioned above. Instead of using left positioning, it is recommended to utilize top and bottom positioning based on the image provided. This adjustment cannot be achieved solely through CSS as the left position changes dynamically when a tab is tapped or clicked. In your CSS file, make sure to include the following code:

.mat-ink-bar {
position: absolute;
bottom: 0;
width: 2px;
transition: .5s cubic-bezier(.35,0,.25,1);

Additionally, consider changing 'height' to 'width' with a value of 2px, while setting the height to match that of the .mat-tab-label.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using JavaScript to dynamically load Cascading Style Sheets based on the current

I am trying to dynamically load different CSS files based on the current date (season). I attempted to tweak an image script that I found on Stack Overflow, but it didn't yield the desired result. Could someone please guide me on where I might be ma ...

The stacking order of a child element within a parent element, which has a transform

Hey there, I've encountered a problem and was wondering if you could assist me with it. In the code snippet provided below, you'll see that there are elements with: transform: translate(0,0); Within these elements, there is a "dropdown" elemen ...

What is the best way to maintain the highlighting of a clicked navigation button in CSS?

.custom-highlight { display: inline; font-weight: 500; font-size: 15px; } .item-list { border: 1px solid #b1b8c9; color: $color-grey-light; font-size: 14px; display: inline-block; margin-right: 8px; padding: 5px 20px; border-radius: 4p ...

Angular 2: Harnessing the power of Observables with multiple Events or Event Handlers

In the component template, I have grouped multiple Inputs and their events like this: <tr (input)="onSearchObjectChange($event)"> <th><input [(ngModel)]="searchObject.prop1"></th> <th><input [(ngModel)]="searchObje ...

Using jQuery to modify CSS attributes is proving to be more challenging than I anticipated

I am attempting to modify a CSS attribute using jQuery. I have used the following code: wrapperInner.css('overflow', 'visible'); However, the value remains unchanged. When I use an alert alert(wrapperInner.css('overflow')), ...

Implementing a button row and content alignment next to an image using Bootstrap or CSS

Ensure that the product detail page features a row with labels and buttons, positioned to the right of the image within Bootstrap columns. I have utilized Bootstrap 3 for this page layout. However, upon implementation, I encountered an issue whereby the b ...

Guide on maintaining Spring Security authentication across Angular front-end

Following the initial feedback on my query, I made adjustments to my Spring Security setup and successfully logged in and accessed a test endpoint using Postman. However, when the same endpoint is called by Angular post successful login, the request fails, ...

Utilize Bootstrap form control class to enhance the appearance of WooCommerce address fields

I'm struggling to incorporate the bootstrap class "form-control" into all of the woocommerce address fields in my account and during the checkout process. Essentially, I am attempting to apply the "form-control" class to both the billing and shipping ...

How can you determine whether the CSS of a <div> is defined in a class or an id using JavaScript/jQuery?

Hey there, I'm currently working on dynamically changing the CSS of a website. Let's say we have a div like this: <div id="fooid" class="fooclass" ></div> The div has a class "fooclass" and an ID "fooid", and we're getting its ...

Extend mat-table with 3 expanding columns and 1 clickable column

Is there a way to add different click events for specific columns of an Angular Material Table? Specifically, I would like the left column (Blue/LP) to trigger a click event that passes the LP value, while the right column triggers an expand action. Curren ...

Adding a component to a page in Angular 4: A step-by-step guide

Currently engaged in a project that involves creating a mobile application design within a web application. I'm wondering how to display my Component object on a page using ViewChild? I have a list of PageComponents, below is the PageComponent class ...

Angular two - Communication between parent and children components using a shared service

I am currently working on establishing communication between child components, but according to the documentation, I need to utilize services for this purpose. However, I am facing challenges in accessing service information. When I try to assign the retur ...

What causes old data to linger in component and how to effectively clear it out

Fetching data from NGXS state involves multiple steps. First, we define the state with a default list and loading indicator: @State<CollectionsStateModel>({ name: 'collections', defaults: { collectionList: [], (...), isListLoading: true, ...

Avoiding the page from scrolling to the top when the sidebar is opened (NextJS, Typescript, TailwindCSS)

I'm currently working on a website that features a sidebar for smaller screens. While the sidebar functions properly, I would like to keep the background page fixed in place when the sidebar is active so it does not scroll. In my code, I have utilize ...

One way to target a span inside a label element when a checkbox is checked using React Material UI createStyles is by using CSS selectors in combination with

I need help targeting the span element within a checkbox label in order to change its background color when the checkbox is checked. <div className={classes.container}> <input type="checkbox" id="checkboxid" /> <lab ...

Experiencing problems with the Locale setting when utilizing the formatNumber function in Angular's core functionalities

I am having trouble formatting a number in Angular using the formatNumber function from the Angular documentation. Here is my code snippet: import {formatNumber} from '@angular/common'; var testNumber = 123456.23; var x = formatNumber(Numb ...

What is the best way to ensure that a global variable is populated after subscribing to an asynchronous event?

Recently, I encountered an async firebase call that looks something like this: this.fbProvider.fbGetProfile() .subscribe(p => { this.profile = p; ...

What is causing elements like divs, paragraphs, or text not to display within an ion-item after an ion-input is added?

I am currently working on validating a simple form and everything seems to be functioning properly. However, I have encountered an issue with displaying text messages within an ionic 3 list item. The ion-item consists of an ion-input element. When I place ...

How to pass an array as parameters in an Angular HTTP GET request to an API

Hey there! I'm relatively new to Angular and I've hit a roadblock. I need to send an array as parameters to a backend API, which specifically expects an array of strings. const params = new HttpParams(); const depKey = ['deploymentInprogre ...

Customize the Underline Color in MaterialUI Select Component

I'm experimenting with MaterialUI and trying to figure out how to customize the underline and text color of the Select component when an item is selected. Currently, the underline and label appear blue after selection with a gray background. Is there ...