REGISTRATION OPENS OCTOBER 26
Registration for Winter 2026 and Spring 2027 opens at midnight on October 26.
PROGRAMS AND COURSES
Find Your Path
We offer more than 300 degrees and certificates, both credit and non-credit.
What do you want to study?
BROWSE BY
SUPPORT SERVICES
Dedicated Faculty and Staff
At CT State you don’t have to do it alone.
FINANCIAL AID
Invest in Your Education
We believe all students should have affordable access to a CT State education.
Take a Tour/Visit
One-Stop Enrollment
Paying For College
Advising
12 Campuses.
5 Satellite Locations.
1 Application.
Upcoming Information Sessions
More Info Sessions
// Smooth number animation helper
function animateValue(el, start, end, duration, formatFn) {
const startTime = performance.now();
function update(now) {
const elapsed = now - startTime;
const progress = Math.min(elapsed / duration, 1);
const value = Math.floor(start + (end - start) * progress);
el.textContent = formatFn(value);
if (progress {
if (el.dataset.animated === "true") return; // avoid re-running
el.dataset.animated = "true";
const type = el.dataset.type || "plain";
if (type === "ratio") {
// Example: 1:15 → animate the "15"
const left = el.dataset.left || "1";
const rightTarget = parseInt(el.dataset.right || "0", 10) || 0;
animateValue(
el,
0,
rightTarget,
1200,
(val) => `${left}:${val}`
);
} else if (type === "currency") {
const target = parseInt(el.dataset.target || "0", 10) || 0;
animateValue(
el,
0,
target,
1200,
(val) => "$" + val.toLocaleString()
);
} else if (type === "plus") {
const target = parseInt(el.dataset.target || "0", 10) || 0;
animateValue(
el,
0,
target,
1200,
(val) => val.toLocaleString() + "+"
);
} else {
// Fallback: just a plain number
const target = parseInt(el.textContent.replace(/\D/g, "") || "0", 10) || 0;
animateValue(
el,
0,
target,
1200,
(val) => val.toLocaleString()
);
}
});
}
// Start animation when the stats section scrolls into view
document.addEventListener("DOMContentLoaded", () => {
const section = document.querySelector(".stats-container");
if (!section) return;
const observer = new IntersectionObserver(
(entries, obs) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
runStatsAnimation();
obs.disconnect(); // run once
}
});
},
{ threshold: 0.3 }
);
observer.observe(section);
});
// Smooth number animation helper
function animateValue(el, start, end, duration, formatFn) {
const startTime = performance.now();
function update(now) {
const elapsed = now - startTime;
const progress = Math.min(elapsed / duration, 1);
const value = Math.floor(start + (end - start) * progress);
el.textContent = formatFn(value);
if (progress {
if (el.dataset.animated === "true") return; // avoid re-running
el.dataset.animated = "true";
const type = el.dataset.type || "plain";
if (type === "ratio") {
// Example: 1:15 → animate the "15"
const left = el.dataset.left || "1";
const rightTarget = parseInt(el.dataset.right || "0", 10) || 0;
animateValue(
el,
0,
rightTarget,
1200,
(val) => `${left}:${val}`
);
} else if (type === "currency") {
const target = parseInt(el.dataset.target || "0", 10) || 0;
animateValue(
el,
0,
target,
1200,
(val) => "$" + val.toLocaleString()
);
} else if (type === "plus") {
const target = parseInt(el.dataset.target || "0", 10) || 0;
animateValue(
el,
0,
target,
1200,
(val) => val.toLocaleString() + "+"
);
} else {
// Fallback: just a plain number
const target = parseInt(el.textContent.replace(/\D/g, "") || "0", 10) || 0;
animateValue(
el,
0,
target,
1200,
(val) => val.toLocaleString()
);
}
});
}
// Start animation when the stats section scrolls into view
document.addEventListener("DOMContentLoaded", () => {
const section = document.querySelector(".stats-container");
if (!section) return;
const observer = new IntersectionObserver(
(entries, obs) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
runStatsAnimation();
obs.disconnect(); // run once
}
});
},
{ threshold: 0.3 }
);
observer.observe(section);
});
// Smooth number animation helper
function animateValue(el, start, end, duration, formatFn) {
const startTime = performance.now();
function update(now) {
const elapsed = now - startTime;
const progress = Math.min(elapsed / duration, 1);
const value = Math.floor(start + (end - start) * progress);
el.textContent = formatFn(value);
if (progress {
if (el.dataset.animated === "true") return; // avoid re-running
el.dataset.animated = "true";
const type = el.dataset.type || "plain";
if (type === "ratio") {
// Example: 1:15 → animate the "15"
const left = el.dataset.left || "1";
const rightTarget = parseInt(el.dataset.right || "0", 10) || 0;
animateValue(
el,
0,
rightTarget,
1200,
(val) => `${left}:${val}`
);
} else if (type === "currency") {
const target = parseInt(el.dataset.target || "0", 10) || 0;
animateValue(
el,
0,
target,
1200,
(val) => "$" + val.toLocaleString()
);
} else if (type === "plus") {
const target = parseInt(el.dataset.target || "0", 10) || 0;
animateValue(
el,
0,
target,
1200,
(val) => val.toLocaleString() + "+"
);
} else {
// Fallback: just a plain number
const target = parseInt(el.textContent.replace(/\D/g, "") || "0", 10) || 0;
animateValue(
el,
0,
target,
1200,
(val) => val.toLocaleString()
);
}
});
}
// Start animation when the stats section scrolls into view
document.addEventListener("DOMContentLoaded", () => {
const section = document.querySelector(".stats-container");
if (!section) return;
const observer = new IntersectionObserver(
(entries, obs) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
runStatsAnimation();
obs.disconnect(); // run once
}
});
},
{ threshold: 0.3 }
);
observer.observe(section);
});
// Smooth number animation helper
function animateValue(el, start, end, duration, formatFn) {
const startTime = performance.now();
function update(now) {
const elapsed = now - startTime;
const progress = Math.min(elapsed / duration, 1);
const value = Math.floor(start + (end - start) * progress);
el.textContent = formatFn(value);
if (progress {
if (el.dataset.animated === "true") return; // avoid re-running
el.dataset.animated = "true";
const type = el.dataset.type || "plain";
if (type === "ratio") {
// Example: 1:15 → animate the "15"
const left = el.dataset.left || "1";
const rightTarget = parseInt(el.dataset.right || "0", 10) || 0;
animateValue(
el,
0,
rightTarget,
1200,
(val) => `${left}:${val}`
);
} else if (type === "currency") {
const target = parseInt(el.dataset.target || "0", 10) || 0;
animateValue(
el,
0,
target,
1200,
(val) => "$" + val.toLocaleString()
);
} else if (type === "plus") {
const target = parseInt(el.dataset.target || "0", 10) || 0;
animateValue(
el,
0,
target,
1200,
(val) => val.toLocaleString() + "+"
);
} else {
// Fallback: just a plain number
const target = parseInt(el.textContent.replace(/\D/g, "") || "0", 10) || 0;
animateValue(
el,
0,
target,
1200,
(val) => val.toLocaleString()
);
}
});
}
// Start animation when the stats section scrolls into view
document.addEventListener("DOMContentLoaded", () => {
const section = document.querySelector(".stats-container");
if (!section) return;
const observer = new IntersectionObserver(
(entries, obs) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
runStatsAnimation();
obs.disconnect(); // run once
}
});
},
{ threshold: 0.3 }
);
observer.observe(section);
});
// Smooth number animation helper
function animateValue(el, start, end, duration, formatFn) {
const startTime = performance.now();
function update(now) {
const elapsed = now - startTime;
const progress = Math.min(elapsed / duration, 1);
const value = Math.floor(start + (end - start) * progress);
el.textContent = formatFn(value);
if (progress {
if (el.dataset.animated === "true") return; // avoid re-running
el.dataset.animated = "true";
const type = el.dataset.type || "plain";
if (type === "ratio") {
// Example: 1:15 → animate the "15"
const left = el.dataset.left || "1";
const rightTarget = parseInt(el.dataset.right || "0", 10) || 0;
animateValue(
el,
0,
rightTarget,
1200,
(val) => `${left}:${val}`
);
} else if (type === "currency") {
const target = parseInt(el.dataset.target || "0", 10) || 0;
animateValue(
el,
0,
target,
1200,
(val) => "$" + val.toLocaleString()
);
} else if (type === "percent") {
const target = parseInt(el.dataset.target || "0", 10) || 0;
animateValue(
el,
0,
target,
1200,
(val) => val.toLocaleString() + "%"
);
} else if (type === "plus") {
const target = parseInt(el.dataset.target || "0", 10) || 0;
animateValue(
el,
0,
target,
1200,
(val) => val.toLocaleString() + "+"
);
} else {
// Fallback: just a plain number
const target = parseInt(el.textContent.replace(/\D/g, "") || "0", 10) || 0;
animateValue(
el,
0,
target,
1200,
(val) => val.toLocaleString()
);
}
});
}
// Start animation when the stats section scrolls into view
document.addEventListener("DOMContentLoaded", () => {
const section = document.querySelector(".stats-container");
if (!section) return;
const observer = new IntersectionObserver(
(entries, obs) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
runStatsAnimation();
obs.disconnect(); // run once
}
});
},
{ threshold: 0.3 }
);
observer.observe(section);
});
// Smooth number animation helper
function animateValue(el, start, end, duration, formatFn) {
const startTime = performance.now();
function update(now) {
const elapsed = now - startTime;
const progress = Math.min(elapsed / duration, 1);
const value = Math.floor(start + (end - start) * progress);
el.textContent = formatFn(value);
if (progress {
if (el.dataset.animated === "true") return; // avoid re-running
el.dataset.animated = "true";
const type = el.dataset.type || "plain";
if (type === "ratio") {
// Example: 1:15 → animate the "15"
const left = el.dataset.left || "1";
const rightTarget = parseInt(el.dataset.right || "0", 10) || 0;
animateValue(
el,
0,
rightTarget,
1200,
(val) => `${left}:${val}`
);
} else if (type === "currency") {
const target = parseInt(el.dataset.target || "0", 10) || 0;
animateValue(
el,
0,
target,
1200,
(val) => "$" + val.toLocaleString()
);
} else if (type === "percent") {
const target = parseInt(el.dataset.target || "0", 10) || 0;
animateValue(
el,
0,
target,
1200,
(val) => val.toLocaleString() + "%"
);
} else if (type === "plus") {
const target = parseInt(el.dataset.target || "0", 10) || 0;
animateValue(
el,
0,
target,
1200,
(val) => val.toLocaleString() + "+"
);
} else {
// Fallback: just a plain number
const target = parseInt(el.textContent.replace(/\D/g, "") || "0", 10) || 0;
animateValue(
el,
0,
target,
1200,
(val) => val.toLocaleString()
);
}
});
}
// Start animation when the stats section scrolls into view
document.addEventListener("DOMContentLoaded", () => {
const section = document.querySelector(".stats-container");
if (!section) return;
const observer = new IntersectionObserver(
(entries, obs) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
runStatsAnimation();
obs.disconnect(); // run once
}
});
},
{ threshold: 0.3 }
);
observer.observe(section);
});
Upcoming Events
View Full Calendar
News
More News