{"id":11782,"date":"2023-09-28T12:00:25","date_gmt":"2023-09-28T09:00:25","guid":{"rendered":"https:\/\/dhtmlx.com\/blog\/?p=11782"},"modified":"2026-09-15T14:21:29","modified_gmt":"2026-09-15T11:21:29","slug":"deep-dhtmlx-gantt-customization-tasks-month-marker-grid","status":"publish","type":"post","link":"https:\/\/dhtmlx.com\/blog\/deep-dhtmlx-gantt-customization-tasks-month-marker-grid\/","title":{"rendered":"Deep DHTMLX Gantt Customization: New Looks of Tasks, Month Marker, and Customized Grid"},"content":{"rendered":"<p>There are as many requirements as many projects. We often receive requests from developers about how far they can go in customizing DHTMLX Gantt. Not everyone knows that our <a href=\"https:\/\/dhtmlx.com\/docs\/products\/dhtmlxGantt\/\" rel=\"noopener\" target=\"_blank\">JS Gantt chart<\/a> allows changing virtually every aspect of its appearance. The resulting Gantt built with DHTMLX can look very different from the original one. <\/p>\n<p>We start a new series of articles on the blog, where we will uncover the most exemplary cases of customizing DHTMLX Gantt to demonstrate its versatility.<\/p>\n<h5>Use Case: New Project Appearance, Current Month Marker, and Collapsible Grid<\/h5>\n<p>The default view of DHTMLX Gantt displays project and task names written inside bars. The project bar usually has a rectangle shape, just like the task bar, and differs from tasks in color. However, this is not the only way to show projects and tasks in DHTMLX Gantt. Our Gantt chart library is very flexible in terms of customization and allows visualizing data in almost any imaginable way. Don&#8217;t take our word for it, but look at a live example.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2023\/09\/DHTMLX-Gantt-Customization-1024x258.jpg\" alt=\"DHTMLX Gantt Customization\" width=\"1024\" height=\"258\" class=\"aligncenter size-large wp-image-11789\" srcset=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2023\/09\/DHTMLX-Gantt-Customization-1024x258.jpg 1024w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2023\/09\/DHTMLX-Gantt-Customization-300x76.jpg 300w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2023\/09\/DHTMLX-Gantt-Customization-768x194.jpg 768w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2023\/09\/DHTMLX-Gantt-Customization.jpg 1353w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><a href=\"https:\/\/snippet.dhtmlx.com\/j4aantk7?mode=wide\" rel=\"noopener\" target=\"_blank\">Check the code snippet ><\/a><\/p>\n<p>Here, you can see projects nicely depicted with thin, colorful lines and labels on top, project dates and duration marked next to their names. Thus, end-users can quickly grasp how much time each project will take. <\/p>\n<p>Task labels are also located to the right of the task bar. The current month is clearly highlighted in the timescale not to get lost on the timeline. Besides, there is a toggle button for collapsing the grid section to make more room for the Gantt chart.<\/p>\n<p>Such a customization contributes to the transparency of the workflow and can be especially useful for small and medium-sized projects. It also makes your Gantt more user-friendly and easier to manage, switching between the view with an expanded grid section and a full-screen chart.<\/p>\n<h5>Customization Guide<\/h5>\n<p>Let&#8217;s delve into what is under the hood of such a Gantt chart made by DHTMLX.<\/p>\n<h6>Current Month Marker<\/h6>\n<p>We start with the time scales and the vertical marker used in the Gantt timeline. The configuration of scales is specified via the <strong>scales<\/strong> property:<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"text codecolorer\">gantt.config.scales = [<br \/>\n&nbsp; &nbsp; {<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; unit: &quot;quarter&quot;, step: 1, format: function (date) {<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const quarter = (date.getMonth() % 3) + 1;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const year = date.getFullYear();<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return `&lt;b&gt;Q${quarter}&lt;\/b&gt; ${year}`;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; }<br \/>\n&nbsp; &nbsp; },<br \/>\n&nbsp; &nbsp; {<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; unit: &quot;month&quot;, step: 1, format: function (date) {<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const monthName = gantt.date.date_to_str(&quot;%F&quot;)(date)<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const nextDate = gantt.date.add(date, 1, &quot;month&quot;);<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (+date &lt;= +today &amp;&amp; +today &lt;= +nextDate) {<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return `&lt;div class=&quot;current_month&quot;&gt;${monthName}&lt;\/div&gt;`;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else {<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return monthName;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; }<br \/>\n&nbsp; &nbsp; },<br \/>\n]<\/div><\/div>\n<p>In the array of the <strong>scales<\/strong> config, we specify two built-in types of scales, &#8220;quarter&#8221; and &#8220;month&#8221;. In the cells of both scale types, we can display any values or HTML elements, but they won&#8217;t change the width of cells. For instance, one of the cells in the lower scale with names of months includes a custom element with a specific class for coloring this cell with CSS styles. This element highlights the current month, which is specified in the <strong>today<\/strong> parameter:<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"text codecolorer\">const today = new Date(2023, 05, 18)<br \/>\nconst todayMarker = gantt.addMarker({<br \/>\n&nbsp; &nbsp; start_date: today,<br \/>\n&nbsp; &nbsp; css: &quot;today&quot;,<br \/>\n});<\/div><\/div>\n<p>The <strong>today<\/strong> parameter is also used in the <strong>addMarker()<\/strong> method for adding a vertical marker that highlights the current month. In the marker configuration, we specify the <strong>Date<\/strong> object that sets the marker&#8217;s date and the CSS class for adding the marker color. Since we do not apply the <strong>text<\/strong> parameter in the <strong>addMarker()<\/strong> method, the marker will be shown as a simple line.<\/p>\n<h6>Task Behavior<\/h6>\n<p>It is necessary to say a few words about the interaction with tasks in the Gantt timeline. End-users can move a given task along the timeline to any specific point and it won&#8217;t snap to the beginning or end of any cell. To make it happen, we changed the value of the <strong>round_dnd_dates<\/strong> parameter to <em>false<\/em> in the <strong>gantt.config<\/strong> object:<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"text codecolorer\">gantt.config.round_dnd_dates = false;<\/div><\/div>\n<p>Following the requirements of this demo project, we also added the ability to move project tasks and disabled the display of dependencies (links) between tasks and the progress of tasks:<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"text codecolorer\">gantt.config.drag_project = true;<br \/>\ngantt.config.drag_progress = false;<br \/>\ngantt.config.drag_links = false;<\/div><\/div>\n<h6>Grid<\/h6>\n<p>Let&#8217;s move on to the grid section. In the grid part of the Gantt chart, there are two columns. The first column contains the names of tasks, while the second one provides their timeframes. Using the <strong>template<\/strong> function, you can add any text or HTML elements in the cells of the grid column:<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"text codecolorer\">gantt.config.columns = [<br \/>\n&nbsp; &nbsp; { name: &quot;text&quot;, label: &quot; &quot;, width: 300, tree: true },<br \/>\n&nbsp; &nbsp; {<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; name: &quot;dates&quot;, label: getToggleButton(), align: &quot;center&quot;, template: function (task) {<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (task.type == &quot;project&quot;) {<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return &quot;&quot;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br \/>\n<br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return taskDatesFormat(task)<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; }<br \/>\n&nbsp; &nbsp; },<br \/>\n];<\/div><\/div>\n<p>Now we want to focus on the <strong>taskDatesFormat<\/strong> function that returns the needed string from a task object:<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"text codecolorer\">function taskDatesFormat(task) {<br \/>\n&nbsp; &nbsp; let startMonth = gantt.date.date_to_str(&quot;%M&quot;);<br \/>\n&nbsp; &nbsp; let endMonth = startMonth;<br \/>\n&nbsp; &nbsp; let day = gantt.date.date_to_str(&quot;%j&quot;);<br \/>\n<br \/>\n<br \/>\n&nbsp; &nbsp; if (task.start_date.getMonth() == task.end_date.getMonth()) {<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; endMonth = gantt.date.date_to_str(&quot;&quot;);<br \/>\n&nbsp; &nbsp; }<br \/>\n&nbsp; &nbsp; const start_date = `${startMonth(task.start_date)} ${day(task.start_date)} - `;<br \/>\n&nbsp; &nbsp; const end_date = `${endMonth(task.end_date)} ${day(task.end_date)}`;<br \/>\n&nbsp; &nbsp; return start_date + end_date;<br \/>\n<br \/>\n}<\/div><\/div>\n<p>This function works as follows:<\/p>\n<ul>\n<li>It converts the task start date into a string, thereby showing only the month&#8217;s name.<\/li>\n<li>If a task starts and ends in the same month, the month&#8217;s name will be seen only before the start date. If start and end dates belong to different months, the start month will show before the start date and the end month &#8211; before the end date.<\/li>\n<li>Dates follow the name of the month.<\/li>\n<\/ul>\n<p>There is a special toggle button that allows collapsing and expanding the grid section. To add this button, we specified the <strong>getToggleButton()<\/strong> function inside the label parameter. Depending on the current state of the grid, this function returns different values. When the button is clicked, we change the return value and the width in the <strong>grid_width<\/strong> config:<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"text codecolorer\">function toggleGrid() {<br \/>\n&nbsp; &nbsp; if (gridToggleText == &quot;lt&quot;) {<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; gantt.config.grid_width = 80;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; gridToggleText = &quot;gt&quot;<br \/>\n&nbsp; &nbsp; }<br \/>\n&nbsp; &nbsp; else {<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; gantt.config.grid_width = initialGridWidth;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; gridToggleText = &quot;lt&quot;<br \/>\n&nbsp; &nbsp; }<br \/>\n&nbsp; &nbsp; gantt.config.columns[1].label = getToggleButton();<br \/>\n&nbsp; &nbsp; gantt.render();<br \/>\n}<\/div><\/div>\n<p>Alternatively, the grid size can be changed with a resizer. The <strong>min_grid_column_width<\/strong> parameter sets the minimum width for each column, so you cannot make the grid smaller than the specified size. Since our Gantt chart has two columns and the value of the <strong>min_grid_column_width<\/strong> parameter is 30px, the minimum grid width is 60px.<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"text codecolorer\">gantt.config.min_grid_column_width = 30;<\/div><\/div>\n<p>Colored circles in the grid area are specified in the <strong>grid_folder<\/strong> template:<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"text codecolorer\">gantt.templates.grid_folder = function (task) {<br \/>\n&nbsp; &nbsp; return `&lt;div style=&quot;color:${task.color}&quot; class=&quot;project_icon&quot;&gt;&amp;nbsp;\u2022&amp;nbsp;&lt;\/div&gt;`;<br \/>\n};<\/div><\/div>\n<p>The returned custom element includes a special symbol &#8220;\u2022&#8221;. The color and size of circles are specified with CSS styles. <\/p>\n<p>The <strong>grid_folder<\/strong> template is displayed for tasks with child elements, while an empty string (&#8220;&#8221;) is returned in the <strong>grid_file<\/strong> template for other tasks:<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"text codecolorer\">gantt.templates.grid_file = function (item) {<br \/>\n&nbsp; &nbsp; return &quot;&quot;;<br \/>\n};<\/div><\/div>\n<p>The <strong>task_row_class<\/strong> template hides a border under tasks with child elements:<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"text codecolorer\">gantt.templates.task_row_class = function (start, end, task) {<br \/>\n&nbsp; &nbsp; if (task.type == &quot;project&quot;) {<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; return &quot;project_row&quot;;<br \/>\n&nbsp; &nbsp; }<br \/>\n};<\/div><\/div>\n<h6>Task Appearance<\/h6>\n<p>Finally, let&#8217;s shed some light on how to customize projects and tasks in the Gantt chart. Since there should be no text inside taskbars, the <strong>task_text<\/strong> template returns an empty string:<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"text codecolorer\">gantt.templates.task_text = function (start, end, task) {<br \/>\n&nbsp; &nbsp; return &quot;&quot;;<br \/>\n};<\/div><\/div>\n<p>Text labels are displayed on the right side with the help of the <strong>rightside_text<\/strong> template:<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"text codecolorer\">gantt.templates.rightside_text = function (start, end, task) {<br \/>\n&nbsp; &nbsp; if (task.type != &quot;project&quot;) {<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; return task.text;<br \/>\n&nbsp; &nbsp; }<br \/>\n};<\/div><\/div>\n<p>In our demo, the <strong>rightside_text<\/strong> template doesn&#8217;t return anything for project tasks. Instead, we use the <strong>addTaskLayer()<\/strong> method, which allows displaying any text or HTML element inside the Gantt timeline. For project tasks, we return a task name, its duration, and dates in the same format used in the Gantt grid with the help of the custom <strong>taskDatesFormat<\/strong> function. These values are separated from one another with a special dot symbol &#8220;\u2022&#8221;. The positioning of custom elements is calculated using the <strong>getTaskPosition()<\/strong> method:<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"text codecolorer\">gantt.addTaskLayer(function (task) {<br \/>\n&nbsp; &nbsp; if (task.type == &quot;project&quot;) {<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; const sizes = gantt.getTaskPosition(task, task.start_date, task.end_date);<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; const el = document.createElement('div');<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; const dot = `&lt;span class=&quot;dot&quot;&gt;\u2022&lt;\/span&gt;`<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; el.innerHTML = task.text + dot + taskDatesFormat(task) + dot + task.duration + &quot;days&quot;;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; el.style.left = sizes.left + 10 + 'px';<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; el.style.top = sizes.top + 'px';<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; el.style.zIndex = 1;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; el.style.marginTop = &quot;7px&quot;;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; el.style.position = &quot;absolute&quot;;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; el.style.lineHeight = &quot;16px&quot;;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; return el;<br \/>\n&nbsp; &nbsp; }<br \/>\n});<\/div><\/div>\n<p>That&#8217;s it! With this step-by-step guide, you can achieve the same result and create a custom Gantt chart like <a href=\"https:\/\/snippet.dhtmlx.com\/j4aantk7?mode=wide\" rel=\"noopener\" target=\"_blank\">in our use case<\/a>.<\/p>\n<h5>Conclusion<\/h5>\n<p>The rich API of the DHTMLX Gantt component allows you to customize the look and feel of almost any element to your liking. So, if your web project lacks a Gantt chart and you have a clear vision of how it should look, DHTMLX Gantt will help bring your idea to life much faster. You can estimate its capabilities by downloading a <a href=\"https:\/\/dhtmlx.com\/docs\/products\/dhtmlxGantt\/download.shtml\" rel=\"noopener\" target=\"_blank\">free 30-day trial version<\/a>. Most of highlighted Gantt customizations can also be reproduced in DHTMLX Gantt v10+ using the <a href=\"https:\/\/dhtmlx.com\/docs\/products\/dhtmlxGantt\/open-source\/\" rel=\"noopener\" target=\"_blank\">Community edition under the MIT license<\/a>.<\/p>\n<p>Also, feel free to <a href=\"mailto:contact@dhtmlx.com\" rel=\"noopener\" target=\"_blank\">send us your ideas<\/a> for Gantt customizations &#8211; and our tech support team will do their best to help you achieve the desired result.<\/p>\n<h5>Related Materials:<\/h5>\n<ul>\n<li>Custom Content in the Timeline of DHTMLX Gantt: <a href=\"https:\/\/dhtmlx.com\/blog\/custom-content-timeline-javascript-gantt-part-1\/\" rel=\"noopener\" target=\"_blank\">Part 1<\/a> and <a href=\"https:\/\/dhtmlx.com\/blog\/custom-content-timeline-javascript-gantt-part-2\/\" rel=\"noopener\" target=\"_blank\">Part 2<\/a><\/li>\n<li><a href=\"https:\/\/snippet.dhtmlx.com\/eq70o558?tag=gantt&#038;mode=wide\" rel=\"noopener\" target=\"_blank\">200+ Code Snippets with DHTMLX Gantt<\/a><\/li>\n<li><a href=\"https:\/\/docs.dhtmlx.com\/gantt\/\" rel=\"noopener\" target=\"_blank\">DHTMLX Gantt Documentation<\/a><\/li>\n<li><a href=\"https:\/\/docs.dhtmlx.com\/gantt\/demos\/\" rel=\"noopener\" target=\"_blank\">100+ DHTMLX Gantt Samples<\/a><\/li>\n<li><a href=\"https:\/\/dhtmlx.com\/docs\/products\/dhtmlxGantt\/download.shtml\" rel=\"noopener\" target=\"_blank\">30-day Free Trial Version<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>There are as many requirements as many projects. We often receive requests from developers about how far they can go in customizing DHTMLX Gantt. Not everyone knows that our &#8230;<\/p>\n","protected":false},"author":101012,"featured_media":11792,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[71,1],"tags":[20],"class_list":["post-11782","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","category-uncategorized","tag-gantt"],"_links":{"self":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/11782","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/users\/101012"}],"replies":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/comments?post=11782"}],"version-history":[{"count":11,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/11782\/revisions"}],"predecessor-version":[{"id":15888,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/11782\/revisions\/15888"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/media\/11792"}],"wp:attachment":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/media?parent=11782"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/categories?post=11782"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/tags?post=11782"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}